본문 바로가기
AI/Coding_Test

Day 14) 프로그래머스 파이썬 반복문과 리스트 5문제 풀이

by 거대웅 TitanBear 2026. 7. 22.

Programmers Coding Test · Day 14 · Python

Day 14
파이썬 반복문과 리스트 5문제 풀이

슬라이싱, 두 리스트 동시 순회, 누적 합, 인덱스와 값의 차이를 직접 작성한 코드의 수정 과정과 함께 정리했습니다.

오늘 문제들은 모두 리스트를 순서대로 다룬다는 공통점이 있지만, 필요한 도구는 조금씩 달랐다. 결과 리스트를 새로 만드는 문제에서는 슬라이싱과 리스트 컴프리헨션이 잘 맞았고, 조건을 만족하는 순간 계산을 끝내야 하는 문제에서는 일반 for문과 조기 반환이 더 자연스러웠다.

이번 기록에서 확인한 기준 코드가 짧은지보다 문제의 결과 형태와 종료 시점에 맞는지가 먼저다. 슬라이싱은 간결하지만 새 리스트를 만들고, range(s, e + 1)은 범위를 직접 제한하므로 같은 조건을 다시 if로 검사할 필요가 없다.

문제 및 공식 링크

프로그래머스 코딩 기초 트레이닝 Day 14
순서문제핵심 개념
1홀수 vs 짝수인덱스의 홀짝, max()
25명씩슬라이싱의 간격
3할 일 목록enumerate(), zip()
4n보다 커질 때까지 더하기누적 합, 조기 반환
5수열과 구간 쿼리 1인덱스와 값, 구간 반복

1. 홀수 vs 짝수

첫 번째 원소를 1번 원소라고 할 때 홀수 번째 원소의 합과 짝수 번째 원소의 합 중 더 큰 값을 반환하는 문제다. 사람의 홀수 번째 위치는 파이썬의 짝수 인덱스 0, 2, 4, ...에 해당한다.

내 풀이

def solution(num_list):
    answer1 = 0
    answer2 = 0

    for i in range(len(num_list)):
        if i % 2 == 0:
            answer1 += num_list[i]
        else:
            answer2 += num_list[i]

    return answer1 if answer1 > answer2 else answer2

이 풀이는 정확한 정답이다. 인덱스가 짝수면 문제에서 말하는 홀수 번째 원소이고, 인덱스가 홀수면 짝수 번째 원소다. 두 합이 같을 때는 answer2를 반환하지만 두 값이 같으므로 결과에는 문제가 없다.

같은 효율로 조금 더 간단하게

def solution(num_list):
    odd_sum = 0
    even_sum = 0

    for i, num in enumerate(num_list):
        if i % 2 == 0:
            odd_sum += num
        else:
            even_sum += num

    return max(odd_sum, even_sum)

enumerate()로 인덱스와 값을 함께 받고, 마지막 비교는 max()에 맡겼다. 시간 복잡도는 O(N), 결과 합계 외에 별도 리스트를 만들지 않으므로 추가 공간은 O(1)이다.

슬라이싱을 사용한 짧은 풀이

def solution(num_list):
    return max(sum(num_list[::2]), sum(num_list[1::2]))
짧은 코드와 메모리 사용량 두 슬라이싱은 각각 새 리스트를 만들므로 추가 공간은 O(N)이다. 다만 이 문제는 리스트 길이가 최대 50이어서 실제 제출에서 메모리 문제가 될 수준은 아니다. 여기서는 성능 경고보다 슬라이싱이 새 리스트를 만든다는 사실을 이해하는 것이 중요하다.

검산: [4, 2, 6, 1, 7, 6]의 홀수 번째 합은 17, 짝수 번째 합은 9이므로 결과는 17이다.

2. 5명씩

이름을 앞에서부터 5명씩 묶고 각 그룹의 첫 번째 사람을 반환하는 문제다. 필요한 인덱스는 0, 5, 10, ...이다.

내 풀이

def solution(names):
    answer = names[::5]
    return answer

수정할 오류가 없는 정답이다. 슬라이싱의 형태는 [start:stop:step]이고, 시작과 끝을 생략한 [::5]는 처음부터 끝까지 5칸 간격으로 선택한다.

직접 반환하기

def solution(names):
    return names[::5]

결과를 새 리스트로 반환해야 하는 문제이므로 슬라이싱이 만드는 새 리스트가 문제의 목적과 잘 맞는다. 공식 예제에서는 0번의 "nami"와 5번의 "vex"가 선택된다.

3. 할 일 목록

todo_list와 같은 위치의 finished 값을 확인해 아직 끝내지 않은 일만 순서대로 모으는 문제다.

내 풀이

def solution(todo_list, finished):
    answer = []

    for i in range(len(todo_list)):
        if finished[i] == False:
            answer.append(todo_list[i])

    return answer

이 코드도 정확한 정답이다. 인덱스 i를 이용해 두 리스트의 같은 위치를 연결했다. 다만 불리언 값이 거짓인지 확인할 때는 == False보다 not을 쓰면 의도가 더 자연스럽게 읽힌다.

enumerate()로 정리한 풀이

def solution(todo_list, finished):
    answer = []

    for i, task in enumerate(todo_list):
        if not finished[i]:
            answer.append(task)

    return answer

zip()과 리스트 컴프리헨션

def solution(todo_list, finished):
    return [task for task, is_finished in zip(todo_list, finished)
            if not is_finished]

zip()은 두 리스트의 같은 위치에 있는 값을 한 쌍씩 묶는다. 인덱스가 필요 없는 이 문제에서는 할 일과 완료 여부를 직접 받는 풀이가 가장 간결하다. 다만 두 입력의 길이가 다르면 짧은 쪽에서 멈춘다는 특성이 있으며, 이 문제에서는 두 배열의 위치가 대응하므로 그대로 사용할 수 있다.

검산: [True, False, True, False]에서는 두 번째와 네 번째 할 일만 결과에 들어간다.

4. n보다 커질 때까지 더하기

배열의 원소를 앞에서부터 누적해 더하다가 합이 n보다 커지는 순간의 합을 반환하는 문제다.

처음 작성한 코드

def solution(numbers, n):
    return [sum(numbers[i]) for i, num in enumerate(numbers)
            if sum(numbers[i]) > n]
1
정수 하나에는 sum()을 사용할 수 없다numbers[i]는 리스트가 아니라 정수 하나다. 따라서 sum(numbers[i])TypeError를 발생시킨다.
2
문제가 요구하는 결과는 리스트가 아니다조건을 만족하는 여러 합을 모으는 것이 아니라 처음으로 n을 넘은 합계 하나를 반환해야 한다.
3
반복 슬라이싱은 같은 값을 다시 더한다sum(numbers[:i + 1])로 문법만 고치면 매 단계마다 앞부분을 새로 만들고 다시 합산해 최악의 경우 O(N²)이 된다.

누적 합을 사용한 기본 풀이

def solution(numbers, n):
    total = 0

    for num in numbers:
        total += num

        if total > n:
            return total

이전 합을 total에 보관하므로 각 원소를 한 번만 더한다. 조건을 만족하는 순간 바로 반환해 뒤쪽 원소도 확인하지 않는다. 시간 복잡도는 실제로 확인한 원소 수를 K라고 할 때 O(K), 추가 공간은 O(1)이다.

itertools.accumulate()를 사용한 풀이

from itertools import accumulate


def solution(numbers, n):
    return next(total for total in accumulate(numbers) if total > n)

accumulate()는 누적 합을 하나씩 생성하고, next()는 조건을 만족하는 첫 값을 꺼낸다. 문제 조건상 전체 합은 반드시 n보다 크므로 기본값은 필요 없다. 처음 배우는 단계에서는 일반 반복문 풀이가 흐름을 더 잘 보여준다.

검산: [34, 5, 71, 29, 100, 34]를 차례로 더하면 34, 39, 110, 139가 되고 123을 처음 넘은 139를 반환한다.

5. 수열과 구간 쿼리 1

각 쿼리 [s, e]마다 s ≤ i ≤ e를 만족하는 모든 인덱스의 값에 1을 더하는 문제다.

처음 작성한 코드

def solution(arr, queries):
    for i in arr:
        for s, e in queries:
            if i >= s and e >= i:
                arr[i] += 1

    return arr
핵심 오류: i에는 인덱스가 아니라 값이 들어간다 for i in arr에서 i는 0, 1, 2 같은 위치가 아니라 배열에 저장된 실제 값이다. 그 값을 다시 arr[i]의 인덱스로 쓰면 범위를 벗어나거나 엉뚱한 원소를 수정할 수 있다.

처음 생각한 흐름을 유지한 수정 풀이

def solution(arr, queries):
    for i in range(len(arr)):
        for s, e in queries:
            if s <= i <= e:
                arr[i] += 1

    return arr

인덱스 전체를 순회하면서 각 쿼리 범위에 포함되는지 확인하는 방식이다. 원래 의도를 그대로 살린 정답이지만 배열의 모든 인덱스와 모든 쿼리를 비교하므로 시간 복잡도는 O(NQ)다.

필요한 구간만 방문하는 풀이

def solution(arr, queries):
    for s, e in queries:
        for i in range(s, e + 1):
            arr[i] += 1

    return arr
1
쿼리를 먼저 꺼낸다현재 처리할 시작점 s와 끝점 e를 먼저 정한다.
2
끝점 e를 포함한다range()는 끝값을 포함하지 않으므로 e + 1까지 지정한다.
3
if 조건은 이미 범위에 들어 있다range(s, e + 1)에서 나오는 모든 i는 처음부터 s ≤ i ≤ e를 만족하므로 같은 조건을 다시 검사할 필요가 없다.

이 방식의 반복 횟수는 각 쿼리 길이의 합인 O(Σ(e - s + 1))이다. 모든 범위가 배열 전체라면 O(NQ)와 같지만, 짧은 구간이 많을수록 불필요한 비교를 줄인다.

검산: [0, 1, 2, 3, 4][[0, 1], [1, 2], [2, 3]]을 차례로 적용하면 최종 결과는 [1, 3, 4, 4, 4]다.

풀이별 복잡도 정리

추천 풀이 기준 시간 및 추가 공간
문제시간추가 공간핵심
홀수 vs 짝수O(N)O(1)두 합만 누적
5명씩O(N)O(N)약 N/5개의 결과 생성
할 일 목록O(N)O(K)미완료 K개 저장
n보다 커질 때까지 더하기O(K)O(1)조건 충족 즉시 반환
수열과 구간 쿼리 1O(구간 길이의 합)O(1)필요한 인덱스만 수정

실수 방지 체크리스트

문제의 홀수 번째와 파이썬의 홀수 인덱스를 같은 것으로 착각하지 않는다.
슬라이싱이 새 리스트를 만든다는 점을 기억한다.
두 리스트의 같은 위치를 다룰 때 인덱스가 필요한지, zip()으로 값을 직접 받을 수 있는지 확인한다.
sum()에는 정수 하나가 아니라 반복 가능한 값의 묶음을 전달한다.
반복 중 계산한 합을 변수에 누적해 같은 구간을 계속 다시 더하지 않는다.
for i in arri는 인덱스가 아니라 값이라는 점을 확인한다.
range()에서 끝점을 포함해야 한다면 1을 더한다.

같이 보면 좋은 자료

1
파이썬 공식 문서: 시퀀스 연산슬라이싱의 시작, 끝, 간격과 리스트 연결 동작을 확인할 수 있다.
2
파이썬 공식 문서: enumerate()반복 가능한 객체에서 인덱스와 값을 함께 얻는 방법이다.
3
파이썬 공식 문서: zip()여러 반복 가능한 객체의 같은 위치 값을 묶어 순회하는 방법이다.
4
파이썬 공식 문서: itertools.accumulate()누적 합과 같은 중간 결과를 순서대로 생성하는 표준 라이브러리 함수다.
마무리

이번 다섯 문제를 풀면서 슬라이싱과 리스트 컴프리헨션이 항상 더 좋은 답은 아니라는 점을 확인했다. 새 리스트가 필요한 문제에서는 간결한 문법이 잘 맞지만, 합이 기준을 넘는 순간 멈춰야 할 때는 누적 변수와 조기 반환이 더 정확하다. 마지막 구간 쿼리 문제에서 값과 인덱스를 구분하고 반복 범위 자체로 조건을 표현한 과정은 이후 배열 문제에서도 계속 사용할 수 있는 기본기가 된다.