260826

Yang Heewon·2026년 8월 26일
post-thumbnail

오늘도 겨우겨우 Day6를 끝냄.
기록은 또... ai에 맡겼다. 코드를 풀면서 적든가 해야지... 끝나고 쓰려니까 기억도 안나고? 집중도 안된다 ㄷㄷ

최근에 잠을 많이 못 자서 그런 것 같기도 하고...

괜찬하아 기록하는 데 의미 잇어

괜찮아내일부턴진짜내가 쓰면돼

1.

각 query는 [s, e, k] 형태이다.

  • s부터 e까지의 인덱스를 확인한다.
  • 해당 범위에서 arr[i]가 k보다 큰 값만 찾는다.
  • 조건을 만족하는 값이 여러 개라면 그중 가장 작은 값을 선택한다.
  • 조건을 만족하는 값이 없다면 -1을 저장한다.
  • 모든 query에 대해 위 과정을 반복하여 결과 배열을 반환한다.

처음 작성 코드

def solution(arr, queries):
    # query = [s, e, k] 꼴
    # 각 쿼리마다 s <= i <= e 인 i 중에서
    # k < arr[i]일 때, 가장 작은 arr[i]

    for query in queries:
        s = query[0]
        e = query[1]
        k = query[2]

        i = (s <= i) and (i <= e)

        if k < arr[i]:
            ...

처음에는 s <= i <= e라는 지문의 조건을 그대로 코드의 조건식으로 만들려고 했다.

하지만 여기서 i는 True/False를 저장하는 변수가 아니라, s부터 e까지 실제 인덱스를 하나씩 움직여야 하는 값이었다.

따라서

i = (s <= i) and (i <= e)

가 아니라,

for i in range(s, e + 1):

처럼 범위를 순회해야 했다.

이후 조건을 만족하는 값을 찾으면서 처음에는 다음과 같이 작성했다.

if k < arr[i]:
    answer += min(arr[i])

하지만 arr[i]는 이미 정수 하나이기 때문에 min()을 사용할 수 없었다.

min()을 사용하려면 먼저 조건을 만족하는 여러 후보를 리스트에 저장한 뒤, 그 리스트에서 최솟값을 구해야 했다.

그래서 후보 리스트를 추가했다.

i_list = []

for i in range(s, e + 1):
    if k < arr[i]:
        i_list.append(arr[i])

여기서 또 하나 헷갈렸던 부분은 min()을 실행하는 위치였다.

처음에는 다음처럼 작성했다.

for i in range(s, e + 1):
    if k < arr[i]:
        i_list.append(arr[i])

        if i_list != []:
            answer.append(min(i_list))

이렇게 작성하면 후보를 하나 발견할 때마다 그 순간의 최솟값이 answer에 계속 들어간다.

이 문제는 query 하나당 결과 하나만 필요하기 때문에, 먼저 범위를 끝까지 돌며 후보를 모두 모은 후 min()을 실행해야 했다.

수정한 최종 코드

def solution(arr, queries):
    answer = []

    for query in queries:
        s = query[0]
        e = query[1]
        k = query[2]

        i_list = []

        for i in range(s, e + 1):
            if k < arr[i]:
                i_list.append(arr[i])

        if i_list != []:
            answer.append(min(i_list))
        else:
            answer.append(-1)

    return answer

이번 문제 핵심: 후보를 먼저 모으고 최종값은 나중에 선택하기

이번 문제에서 가장 헷갈렸던 부분은 반복하면서 하는 일과 반복이 끝난 뒤 하는 일을 구분하는 것이었다.

크게 보면

  1. s ~ e 범위의 인덱스를 순회한다.
  2. arr[i] > k를 만족하는 값을 후보 리스트에 저장한다.
  3. 모든 인덱스를 확인한 뒤 후보가 존재하는지 확인한다.
  4. 후보가 있으면 min(), 없으면 -1을 저장한다.

즉 구조는 다음과 같다.

query 하나 선택
       ↓
s, e, k 분리
       ↓
s ~ e 반복
       ↓
arr[i] > k ?
       ↓
조건 만족 값 후보 리스트에 저장
       ↓
반복 종료
       ↓
후보 있음 → min()
후보 없음 → -1
       ↓
answer에 저장

또 하나 배운 점은 문제에서

s <= i <= e

라고 주어졌다고 해서 항상 그대로 if 조건으로 옮기는 것이 아니라는 점이다.

이번 경우에는 이 문장이 "i가 이 범위를 움직인다"는 뜻이므로

for i in range(s, e + 1):

로 표현하는 것이 적절했다.

그리고

answer

와

i_list

의 역할도 구분해야 했다.

i_list
→ 현재 query 하나를 풀기 위한 임시 후보 저장소

answer
→ 각 query의 최종 결과를 저장하는 리스트

따라서 i_list = []는 새로운 query를 처리할 때마다 초기화되어야 한다.


다른 풀이

후보를 전부 리스트에 저장하지 않고, 현재까지 찾은 최솟값 하나만 기억하는 방법도 있다.

def solution(arr, queries):
    answer = []

    for s, e, k in queries:
        result = -1

        for i in range(s, e + 1):
            if arr[i] > k:
                if result == -1 or arr[i] < result:
                    result = arr[i]

        answer.append(result)

    return answer

이 방식은 후보 리스트를 만들지 않고

조건을 만족하는 값 발견
→ 현재 result보다 작은지 확인
→ 더 작다면 result 교체

하는 방식이다.

현재는 후보를 리스트에 모은 뒤 min()을 사용하는 방식이 더 직관적으로 이해된다.

회고

이번 문제는 조건 자체보다 문제의 문장을 반복문의 구조로 바꾸는 과정에서 많이 막혔다.

특히 s <= i <= e를 보고 처음에는 조건식부터 만들려고 했는데, 실제로 필요한 것은 s부터 e까지 인덱스를 하나씩 확인하는 반복문이었다.

또 조건을 만족하는 순간 바로 답을 구하려고 했지만, "가장 작은 값"은 모든 후보를 확인한 뒤 결정해야 한다는 점도 놓쳤다.

앞으로 문제를 볼 때는 바로 코드를 쓰기보다,

무엇을 반복하는가?
반복하면서 무엇을 모으는가?
반복이 끝난 뒤 무엇을 결정하는가?

를 먼저 나눠보는 연습이 필요할 것 같다.


헷갈린 부분: 음수 인덱싱과 슬라이싱

오늘 리스트의 뒤에서 첫 번째, 두 번째 값을 가져와야 하는 상황에서 list[-1], list[-2] 대신 list[::-1], list[::-2]를 사용했다.

arr = [10, 20, 30, 40, 50]

arr[-1]    # 50
arr[-2]    # 40

arr[::-1]  # [50, 40, 30, 20, 10]
arr[::-2]  # [50, 30, 10]

핵심은 [] 안에 콜론(:)이 있느냐로 구분할 수 있다.

  • arr[-1] → 인덱싱: 뒤에서 1번째 값 하나
  • arr[-2] → 인덱싱: 뒤에서 2번째 값 하나
  • arr[::-1] → 슬라이싱: 뒤에서부터 1칸씩 → 전체 역순
  • arr[::-2] → 슬라이싱: 뒤에서부터 2칸씩 → 역순으로 건너뛰기

회고:
-1을 무조건 "역순"이라고 생각해서 헷갈렸다. 앞으로는 값 하나를 찾는지 → 인덱싱, 여러 값을 일정한 간격으로 자르는지 → 슬라이싱을 먼저 구분해야겠다. 특히 :이 들어가면 [시작:끝:간격] 형태의 슬라이싱이라는 점을 기억하자.

profile
초보개발자

0개의 댓글