본문 바로가기
카테고리 없음

Day 7) 프로그래머스 반복문: 구간 쿼리, 배열 만들기, 콜라츠, 스택 풀이 정리

by 거대웅 TitanBear 2026. 7. 12.

Day 7 코딩테스트 공부 기록

프로그래머스 반복문: 구간 쿼리, 배열 만들기, 콜라츠, 스택 풀이 정리

이번 Day 7은 반복문을 중심으로 정리했습니다. for로 범위를 돌고, while로 조건이 끝날 때까지 반복하고, 리스트에 값을 추가하거나 제거하는 흐름이 계속 나왔습니다.

특히 콜라츠 수열 만들기에서는 종료 조건과 정수 나눗셈이 헷갈렸고, 배열 만들기 4에서는 i, len(arr), arr[i]를 구분하는 부분과 stk.pop()의 의미가 중요했습니다.

핵심 1 range로 구간 반복하기
핵심 2 while 종료 조건 잡기
핵심 3 append와 pop으로 스택 다루기
반복문 문제는 “몇 번 도는가”보다 “언제 값을 바꾸고, 언제 결과에 넣는가”가 더 중요했습니다.

이 글의 풀이 순서

  1. 문제 및 프로그래머스 공식 링크
  2. 내 풀이 또는 처음 헷갈린 코드
  3. 설명 및 잘못된 점
  4. 기본 수정 풀이
  5. 더 간단한 풀이와 설명
  6. 입출력 예로 검산하기

1. 문제 및 프로그래머스 공식 링크

이번 글에서 정리한 문제는 모두 프로그래머스 코딩 기초 트레이닝 Day 7의 반복문 관련 문제입니다.

프로그래머스 Day 7 문제 링크와 핵심 개념
문제 공식 링크 핵심 개념
수열과 구간 쿼리 4 문제 보기 중첩 반복문, 인덱스 조건
배열 만들기 2 문제 보기 문자열 변환, 조건 필터링
카운트 업 문제 보기 range의 끝값 처리
콜라츠 수열 만들기 문제 보기 while 종료 조건, 정수 나눗셈
배열 만들기 4 문제 보기 스택, pop, 오름차순 유지

2. 수열과 구간 쿼리 4: 범위 안에서 조건에 맞는 인덱스만 바꾸기

문제 요약

각 쿼리는 [s, e, k] 형태입니다. 쿼리마다 s부터 e까지의 인덱스 i를 확인하면서, ik의 배수이면 arr[i]에 1을 더합니다.

기본 풀이

def solution(arr, queries):
    for s, e, k in queries:
        for i in range(s, e + 1):
            if i % k == 0:
                arr[i] += 1
    return arr

설명 및 실수 주의

range(s, e + 1)을 쓰는 이유는 파이썬의 range()가 끝값을 포함하지 않기 때문입니다. 문제는 s <= i <= e라고 했으므로 e까지 포함하려면 e + 1을 넣어야 합니다. 또 이 문제에서 배수인지 확인하는 대상은 배열의 값이 아니라 인덱스 i입니다. 그래서 arr[i] % k가 아니라 i % k를 확인합니다.

조금 더 짧게 쓰기

def solution(arr, queries):
    for s, e, k in queries:
        for i in range(s, e + 1):
            arr[i] += int(i % k == 0)
    return arr

조건식이 참이면 True, 거짓이면 False가 됩니다. 파이썬에서 int(True)는 1, int(False)는 0이므로 위처럼 더할 수도 있습니다. 다만 처음 공부할 때는 if문 풀이가 더 읽기 쉽습니다.

3. 배열 만들기 2: 숫자를 문자열로 바꿔 0과 5만 확인하기

문제 요약

l 이상 r 이하의 정수 중에서 숫자 05로만 이루어진 수를 오름차순으로 담아 반환합니다. 조건에 맞는 수가 없다면 [-1]을 반환합니다.

기본 풀이

def solution(l, r):
    answer = []

    for num in range(l, r + 1):
        is_valid = True
        for ch in str(num):
            if ch != '0' and ch != '5':
                is_valid = False
                break

        if is_valid:
            answer.append(num)

    if answer:
        return answer
    return [-1]

설명 및 실수 주의

숫자 안의 각 자릿수를 확인하려면 숫자를 문자열로 바꾸는 것이 편합니다. str(num)으로 바꾸면 각 글자를 for ch in str(num)처럼 하나씩 확인할 수 있습니다. 조건에 맞지 않는 글자를 발견하면 더 볼 필요가 없으므로 break로 빠져나옵니다.

더 간단한 풀이

def solution(l, r):
    answer = []

    for num in range(l, r + 1):
        if all(ch in '05' for ch in str(num)):
            answer.append(num)

    return answer if answer else [-1]

all()은 안쪽 조건이 모두 참일 때만 True를 반환합니다. 그래서 모든 자릿수가 0 또는 5인지 한 줄로 확인할 수 있습니다.

4. 카운트 업: range의 끝값은 포함되지 않는다

문제 요약

start_num부터 end_num까지의 숫자를 차례로 담은 리스트를 반환하는 문제입니다.

기본 풀이

def solution(start_num, end_num):
    answer = []

    for num in range(start_num, end_num + 1):
        answer.append(num)

    return answer

더 간단한 풀이

def solution(start_num, end_num):
    return list(range(start_num, end_num + 1))

이 문제의 핵심은 end_num + 1입니다. range(3, 10)은 3부터 9까지만 만들기 때문에, 10까지 포함하려면 range(3, 11)처럼 끝값보다 1 큰 값을 넣어야 합니다.

5. 콜라츠 수열 만들기: while 종료 조건과 정수 나눗셈

문제 요약

자연수 n에서 시작해, 짝수이면 2로 나누고 홀수이면 3 * n + 1로 바꾸는 과정을 반복합니다. 이 과정에서 지나간 모든 수를 리스트에 담아 반환해야 합니다. 마지막에는 반드시 1이 포함되어야 합니다.

처음 헷갈린 코드

def solution(n):
    list = []
    new = 0

    while n == 1:
        n % 2 if n % 2 == 0 else 3 * n + 1
        list.append(new)
        break

    return list

설명 및 잘못된 점

  • list는 파이썬 내장 이름이므로 변수명으로 쓰지 않는 편이 좋습니다. answerresult가 더 안전합니다.
  • while n == 1은 처음부터 n이 1일 때만 실행됩니다. 콜라츠 수열은 1이 될 때까지 반복해야 하므로 while n != 1 또는 while n > 1을 써야 합니다.
  • n % 2 if ...는 값을 계산만 할 뿐 n에 다시 저장하지 않습니다. n = ...처럼 대입해야 값이 바뀝니다.
  • 짝수일 때 필요한 것은 나머지 n % 2가 아니라 몫 n // 2입니다.
  • break가 조건 없이 들어가면 반복문이 한 번만 돌고 끝납니다.

기본 수정 풀이

def solution(n):
    answer = [n]

    while n != 1:
        if n % 2 == 0:
            n //= 2
        else:
            n = 3 * n + 1

        answer.append(n)

    return answer

더 간단한 풀이

def solution(n):
    answer = []

    while n > 1:
        answer.append(n)
        n = n // 2 if n % 2 == 0 else 3 * n + 1

    answer.append(1)
    return answer
/ 와 // 차이

/는 나눗셈 결과를 실수로 만듭니다. 예를 들어 4 / 22.0입니다. 반면 //는 몫을 구해 정수 흐름을 유지합니다. 콜라츠 수열은 정수 수열이므로 n /= 2보다 n //= 2가 안전합니다.

6. 배열 만들기 4: i, len(arr), arr[i]를 구분해야 한다

문제 요약

배열 arr를 보면서 새 배열 stk를 만듭니다. stk가 비었거나 stk[-1] < arr[i]이면 arr[i]를 넣고 i를 1 증가시킵니다. 반대로 stk[-1] >= arr[i]이면 stk의 마지막 값을 제거하고 i는 그대로 둡니다.

처음 헷갈린 코드

def solution(arr):
    stk = []
    i = 0

    while i < len(arr):
        if stk == []:
            stk.arr[i]
            i += 1
        elif stk != [] and stk[-1] < arr[i]:
            stk.append(arr[i])
            i += 1
        else:
            stk.pop()

    return stk

설명 및 잘못된 점

  • stk.arr[i]는 잘못된 문법입니다. 리스트에 값을 넣을 때는 stk.append(arr[i])를 써야 합니다.
  • i < len(arr)i가 배열의 길이보다 작은지 확인하는 조건입니다. i < arr[i]가 아닙니다.
  • 3번 조건에서 stk.pop()을 할 때는 i를 증가시키지 않습니다. 같은 arr[i]를 새로 바뀐 stk와 다시 비교해야 하기 때문입니다.
  • arr[-1]은 전체 배열의 마지막 원소입니다. 지금 보고 있는 값은 arr[i]입니다.

기본 수정 풀이

def solution(arr):
    stk = []
    i = 0

    while i < len(arr):
        if not stk:
            stk.append(arr[i])
            i += 1
        elif stk[-1] < arr[i]:
            stk.append(arr[i])
            i += 1
        else:
            stk.pop()

    return stk

더 간단한 풀이: 모노토닉 스택

def solution(arr):
    stk = []

    for i in range(len(arr)):
        while stk and stk[-1] >= arr[i]:
            stk.pop()
        stk.append(arr[i])

    return stk

이 코드는 stk 안의 숫자가 항상 오름차순으로 남도록 만듭니다. 새로 들어올 값 arr[i]보다 크거나 같은 값이 스택의 끝에 있으면 계속 pop()으로 제거합니다. 방해되는 값들이 다 사라진 뒤에 현재 값 arr[i]를 추가합니다.

배열 만들기 4 예시 흐름
현재 값 while 동작 append 후 stk
1 스택이 비어 있음 [1]
4 1 < 4라서 제거 없음 [1, 4]
2 4 >= 2라서 4 제거 [1, 2]
5 2 < 5라서 제거 없음 [1, 2, 5]
3 5 >= 3라서 5 제거 [1, 2, 3]
pop, remove, del, clear 차이

pop()은 위치 기준으로 값을 제거하고 제거한 값을 반환합니다. 괄호를 비우면 마지막 값을 제거하므로 스택 문제에서 자주 씁니다. remove()는 특정 값을 찾아 제거하고, del은 인덱스나 변수를 삭제하며, clear()는 리스트 전체를 비웁니다. 이번 문제에서는 마지막 원소를 제거해야 하므로 stk.pop()이 가장 자연스럽습니다.

7. 입출력 예로 빠르게 검산하기

Day 7 문제별 빠른 검산 예시
문제 예시 입력 기대 결과
수열과 구간 쿼리 4 [0,1,2,4,3], [[0,4,1],[0,3,2],[0,3,3]] [3, 2, 4, 6, 4]
배열 만들기 2 l=5, r=555 [5, 50, 55, 500, 505, 550, 555]
카운트 업 start_num=3, end_num=10 [3, 4, 5, 6, 7, 8, 9, 10]
콜라츠 수열 만들기 n=10 [10, 5, 16, 8, 4, 2, 1]
배열 만들기 4 [1, 4, 2, 5, 3] [1, 2, 3]

8. 실수 방지 체크리스트

  • range()는 끝값을 포함하지 않으므로, 끝까지 포함하려면 + 1을 붙인다.
  • 배수 조건을 볼 때 배열의 값인지 인덱스인지 먼저 확인한다.
  • 숫자의 각 자릿수를 확인해야 할 때는 str(num)으로 문자열로 바꿔서 본다.
  • while문은 종료 조건을 잘못 잡으면 무한 루프가 된다.
  • 콜라츠 수열에서 짝수 처리는 /가 아니라 // 또는 //=를 사용한다.
  • i, len(arr), arr[i]는 서로 다른 의미다.
  • 리스트에 값을 넣을 때는 append(), 마지막 값을 뺄 때는 pop()을 떠올린다.
  • arr[-1]은 전체 배열의 마지막 값이고, 반복문에서 현재 보는 값은 arr[i]다.

9. 같이 보면 좋은 글

  • 파이썬 range 기초: 시작값, 끝값, 증가값이 헷갈릴 때 같이 보면 좋습니다.
  • while문과 무한 루프 방지: 반복 종료 조건을 세우는 연습에 도움이 됩니다.
  • append, pop, remove, del 차이: 리스트에 값을 넣고 빼는 문제에서 자주 나옵니다.
  • 모노토닉 스택 입문: 배열 만들기 4처럼 스택을 오름차순으로 유지하는 문제와 연결됩니다.

마무리

Day 7 문제들은 반복문을 많이 쓰지만, 단순히 많이 반복하는 문제가 아니었습니다. 어떤 조건에서 값을 추가할지, 언제 인덱스를 증가시킬지, 언제 반복을 멈출지를 정확히 정해야 했습니다.

특히 콜라츠 수열과 배열 만들기 4는 작은 실수 하나가 바로 무한 루프나 런타임 에러로 이어질 수 있었습니다. 앞으로 비슷한 문제를 풀 때는 반복 조건, 값 갱신, 리스트 추가와 제거 위치를 먼저 확인하는 습관을 들이려고 합니다.