프로그래머스 코딩 기초 트레이닝
마지막 두 원소, 수 조작하기, 구간 쿼리 실수 정리
이번 글은 제가 파이썬으로 프로그래머스 코딩 기초 트레이닝을 풀면서 헷갈렸던 내용을 다시 정리한 기록입니다. 특히 append()의 반환값, =와 ==의 차이, 리스트 인덱스 접근, 딕셔너리 매핑, 그리고 들여쓰기 위치에서 실수가 많이 나왔습니다.
정답 코드만 보면 쉬워 보이지만, 막상 직접 쓰면 어디에서 값이 바뀌고 어디에서 반환해야 하는지 헷갈립니다. 그래서 각 문제마다 처음 헷갈린 코드, 잘못된 점, 기본 수정 풀이, 더 간단한 풀이 순서로 정리했습니다.
이번 문제들은 어려운 알고리즘보다, 파이썬 기본 문법을 정확한 위치에 쓰는 연습에 가까웠습니다.
이 글의 풀이 순서
- 문제 및 프로그래머스 공식 링크
- 내 풀이 또는 처음 헷갈린 코드
- 설명 및 잘못된 점
- 기본 수정 풀이
- 더 간단한 풀이와 설명
- 입출력 예로 검산하기
1. 문제 및 프로그래머스 공식 링크
이번 글에서 정리한 문제는 모두 프로그래머스 코딩 기초 트레이닝 문제입니다.
| 문제 | 공식 링크 | 핵심 개념 |
|---|---|---|
| 마지막 두 원소 | 문제 보기 | 마지막 값과 직전 값 비교, append |
| 수 조작하기 1 | 문제 보기 | 문자별 숫자 변화, 딕셔너리 |
| 수 조작하기 2 | 문제 보기 | 두 값의 차이로 문자 복원 |
| 수열과 구간 쿼리 3 | 문제 보기 | 인덱스 쌍으로 자리 바꾸기 |
| 수열과 구간 쿼리 2 | 문제 보기 | 범위 안에서 k보다 큰 최솟값 찾기 |
2. 마지막 두 원소: append 결과를 변수에 담으면 안 되는 이유
문제 요약
리스트의 마지막 원소가 그전 원소보다 크면 두 값의 차이를 추가하고, 그렇지 않으면 마지막 원소의 두 배를 추가해 리스트를 반환하는 문제입니다.
처음 헷갈린 코드
def solution(num_list):
answer = []
if num_list[-1] > num_list[-2]:
new = num_list[-1] - num_list[-2]
else:
new = num_list[-1] * 2
answer = num_list.append(new)
return answer
설명 및 잘못된 점
핵심 실수는 answer = num_list.append(new)입니다. append()는 리스트에 값을 직접 추가하지만, 그 실행 결과로 새 리스트를 반환하지 않습니다. 그래서 answer에는 리스트가 아니라 None이 들어갑니다. 값을 추가한 뒤에는 바뀐 num_list 자체를 반환해야 합니다.
기본 수정 풀이
def solution(num_list):
if num_list[-1] > num_list[-2]:
new = num_list[-1] - num_list[-2]
else:
new = num_list[-1] * 2
num_list.append(new)
return num_list
더 간단한 풀이
def solution(num_list):
last = num_list[-1]
prev = num_list[-2]
num_list.append(last - prev if last > prev else last * 2)
return num_list
num_list[-1]은 마지막 원소, num_list[-2]는 뒤에서 두 번째 원소입니다. 리스트 끝의 값만 보면 되므로 반복문은 필요하지 않습니다.
3. 수 조작하기 1: =와 ==를 확실히 구분하기
문제 요약
문자열 control을 앞에서부터 읽으며 w, s, d, a에 따라 정수 n을 각각 1 증가, 1 감소, 10 증가, 10 감소시키는 문제입니다.
처음 헷갈린 코드
def solution(n, control):
answer = 0
for char in control:
if char = "w":
answer += 1
설명 및 잘못된 점
if char = "w"는 문법 오류입니다. 조건 비교에는==를 사용해야 합니다.- 문제는 새로 만든
answer = 0을 조작하는 것이 아니라, 매개변수로 받은n을 조작하는 문제입니다. answer를answser처럼 잘못 쓰면 변수명 오타 때문에 오류가 납니다.
=는 변수에 값을 넣는 대입입니다. n = 1은 n 값을 1로 바꿉니다. ==는 두 값이 같은지 비교하는 조건식입니다. char == "w"는 char가 "w"인지 확인합니다.
기본 수정 풀이
def solution(n, control):
for char in control:
if char == "w":
n += 1
elif char == "s":
n -= 1
elif char == "d":
n += 10
else:
n -= 10
return n
더 간단한 풀이
def solution(n, control):
control_dict = {"w": 1, "s": -1, "d": 10, "a": -10}
return n + sum(control_dict[char] for char in control)
문자와 변화량이 일대일로 대응되기 때문에 딕셔너리를 쓰면 조건문을 줄일 수 있습니다.
4. 수 조작하기 2: 값이 아니라 차이를 문자로 바꾸기
문제 요약
정수 배열 numLog에는 조작 후의 값들이 차례대로 들어 있습니다. 연속된 두 값의 차이가 1이면 w, -1이면 s, 10이면 d, -10이면 a를 붙여 원래 조작 문자열을 복원해야 합니다.
처음 헷갈린 코드
def solution(numLog):
ans = ''
c = {"w": 1, "s": -1, "d": 10, "a": -10}
for l in numLog:
# numLog[l + 1]처럼 접근하려고 하면 위험합니다.
pass
설명 및 잘못된 점
for l in numLog에서 l은 인덱스가 아니라 리스트 안의 실제 값입니다. 그래서 numLog[l + 1]처럼 쓰면 의도와 다르게 동작합니다. 이 문제는 현재 값과 다음 값의 차이를 구해야 하므로 인덱스로 접근하거나, zip()으로 앞뒤 값을 묶어야 합니다. 또한 딕셔너리는 문자에서 숫자로 가는 방향이 아니라 숫자 차이에서 문자로 가는 방향이어야 합니다.
기본 수정 풀이
def solution(numLog):
answer = ''
diff_to_char = {1: "w", -1: "s", 10: "d", -10: "a"}
for i in range(1, len(numLog)):
diff = numLog[i] - numLog[i - 1]
answer += diff_to_char[diff]
return answer
더 간단한 풀이
def solution(numLog):
diff_to_char = {1: "w", -1: "s", 10: "d", -10: "a"}
return ''.join(diff_to_char[next_num - cur] for cur, next_num in zip(numLog, numLog[1:]))
zip(numLog, numLog[1:])은 현재 값과 다음 값을 한 쌍으로 묶어줍니다. 그래서 next_num - cur만 계산하면 변화량을 바로 얻을 수 있습니다.
5. 수열과 구간 쿼리 3: queries는 자리 바꾸기 지시서다
문제 요약
queries의 각 원소는 [i, j] 형태입니다. 각 쿼리마다 arr[i]와 arr[j]의 값을 서로 바꾼 뒤, 모든 쿼리를 처리한 최종 배열을 반환합니다.
처음 헷갈린 코드
def solution(arr, queries):
answer = []
for char in queries:
char = queries
설명 및 잘못된 점
반복문에서 꺼낸 char에 다시 queries 전체를 넣으면, 현재 쿼리의 의미가 사라집니다. 이 문제에서 중요한 것은 queries 안의 [i, j]를 하나씩 꺼내 arr의 두 위치를 바꾸는 것입니다. 따라서 for i, j in queries처럼 구조 분해를 사용하는 것이 가장 직관적입니다.
기본 수정 풀이
def solution(arr, queries):
for i, j in queries:
arr[i], arr[j] = arr[j], arr[i]
return arr
arr[i], arr[j] = arr[j], arr[i]는 파이썬에서 두 값을 서로 바꿀 때 자주 쓰는 문법입니다. 임시 변수를 따로 만들지 않아도 됩니다.
6. 수열과 구간 쿼리 2: 최솟값 판단은 안쪽 반복문이 끝난 뒤에
문제 요약
각 쿼리는 [s, e, k] 형태입니다. arr[s]부터 arr[e]까지 보면서 k보다 큰 값 중 가장 작은 값을 찾아야 합니다. 조건에 맞는 값이 없으면 -1을 넣습니다.
처음 헷갈린 흐름
def solution(arr, queries):
answer = []
for s, e, k in queries:
sub_arr = []
for i in range(s, e + 1):
if arr[i] > k:
sub_arr.append(arr[i])
answer.append(min(sub_arr)) # 위치가 너무 빠릅니다.
설명 및 잘못된 점
이 문제에서 가장 중요한 부분은 들여쓰기입니다. 후보를 모두 모으기도 전에 answer.append(min(sub_arr))를 실행하면, 범위를 끝까지 확인하기 전에 결과가 들어가고 쿼리 하나에서 답이 여러 번 추가될 수 있습니다. -1을 넣는 판단도 마찬가지로 안쪽 반복문이 끝난 뒤에 해야 합니다.
기본 수정 풀이
def solution(arr, queries):
answer = []
for s, e, k in queries:
candidates = []
for i in range(s, e + 1):
if arr[i] > k:
candidates.append(arr[i])
if candidates:
answer.append(min(candidates))
else:
answer.append(-1)
return answer
더 간단한 풀이
def solution(arr, queries):
answer = []
for s, e, k in queries:
candidates = [x for x in arr[s:e + 1] if x > k]
answer.append(min(candidates) if candidates else -1)
return answer
arr[s:e + 1]은 s부터 e까지의 구간을 잘라냅니다. 파이썬 슬라이싱은 끝 인덱스를 포함하지 않기 때문에 e + 1을 사용합니다. 그리고 빈 리스트는 조건문에서 거짓처럼 동작하므로 if candidates로 후보가 있는지 확인할 수 있습니다.
7. 입출력 예로 빠르게 검산하기
| 문제 | 예시 입력 | 기대 결과 |
|---|---|---|
| 마지막 두 원소 | [2, 1, 6] |
[2, 1, 6, 5] |
| 수 조작하기 1 | 0, "wsdawsdassw" |
-1 |
| 수 조작하기 2 | [0, 1, 0, 10, 0, 1, 0, 10, 0, -1, -2, -1] |
"wsdawsdassw" |
| 수열과 구간 쿼리 3 | [0,1,2,3,4], [[0,3],[1,2],[1,4]] |
[3, 4, 1, 0, 2] |
| 수열과 구간 쿼리 2 | [0,1,2,4,3], [[0,4,2],[0,3,2],[0,2,2]] |
[3, 4, -1] |
8. 실수 방지 체크리스트
append()는 리스트를 직접 바꾸지만 새 리스트를 반환하지 않는다.=는 대입,==는 비교다.- 문제를 풀 때 새 변수
answer가 필요한지, 기존 입력값을 바꿔 반환해야 하는지 먼저 확인한다. for x in 리스트에서x는 인덱스가 아니라 실제 값이다.- 연속된 두 값의 차이를 봐야 하면
range(1, len(...))또는zip()을 떠올린다. - 쿼리 문제에서는 안쪽 반복문이 끝난 뒤 결과를 한 번만 추가해야 하는 경우가 많다.
- 리스트가 비었는지는
if candidates:,if not candidates:로 간단히 확인할 수 있다.
9. 같이 보면 좋은 글
- 파이썬 리스트 인덱싱 기초:
[-1],[-2], 슬라이싱을 헷갈릴 때 같이 보기 좋습니다. - 파이썬 append와 return 차이: 리스트를 직접 바꾸는 메서드를 이해하는 데 도움이 됩니다.
- 딕셔너리로 조건문 줄이기: 문자와 숫자를 매핑하는 문제에서 자주 쓰입니다.
- 구간 쿼리 문제 읽는 법:
[i, j],[s, e, k]형태의 입력을 해석할 때 도움이 됩니다.
마무리
이번 문제들을 풀면서 가장 크게 느낀 점은, 코딩테스트 초반에는 알고리즘보다 기본 문법 실수가 더 자주 발목을 잡는다는 것입니다. append()를 변수에 담는 실수, =와 ==를 헷갈리는 실수, 값과 인덱스를 섞는 실수만 줄여도 코드가 훨씬 안정적으로 돌아갑니다.
다음에 비슷한 문제를 만나면 먼저 “반복문이 정말 필요한가?”, “반환해야 하는 값은 무엇인가?”, “결과를 언제 추가해야 하는가?”를 확인하려고 합니다. 이 세 가지만 체크해도 같은 실수를 꽤 많이 줄일 수 있을 것 같습니다.
'AI > Coding_Test' 카테고리의 다른 글
| Day5) Programmers Coding Test (0) | 2026.07.11 |
|---|---|
| Day4)Programmers Coding Test (0) | 2026.07.08 |
| Day3) Programmers Coding Test (0) | 2026.07.08 |
| 프로그래머스 DAY 2: 파이썬 문자열 출력과 슬라이싱 한 번에 정리 (0) | 2026.07.06 |