큐는 귀엽다

김키핑·2026년 6월 16일
post-thumbnail

문제

링크

두 큐의 원소 합이 정확히 똑같아지도록 만드는 '최소 작업 횟수'를 구하기.

하나의 큐를 골라 원소를 추출(pop)하고, 추출된 원소를 다른 큐에 집어넣을 때 ,(insert)
두 큐의 원소 합이 정확히 똑같아지도록 만드는 '최소 작업 횟수'를 구하는 문제였다.

※ 두 큐의 합을 같게 만들 수 없는 상황이라면 -1을 반환하도록 한다.


풀이

투포인터

1차원 배열이나 리스트에서 두 개의 점(포인터)을 조작해가며 원하는 값을 찾거나 조건을 만족하는 구간을 탐색하는 기법.
양쪽 범위를 조작하는 것으로 답을 구할 수 있는 문제 (ex. 슬라이드 윈도우 등) 에서 주로 사용한다.


흐름

  1. queue1과 queue2의 원소를 이어붙여 total_sum을 만들고, current_sum 이 target_sum이 될 때까지 투 포인터(l, r)로 queue1의 범위를 확장·축소하며 목표 합(target_sum)을 맞춘다.

  2. 이와 동시에 deque에 담아둔 queue1 queue2 원소들을 투포인터 범위에 기반해 조작하고 작업횟수 moves를 카운트한다.

  3. 최종 moves를 반환한다.


코드

from collections import deque


def solution(queue1, queue2):

    total_sum = sum(queue1) + sum(queue2)
    target_sum = total_sum // 2
    current_sum = sum(queue1)

    # 두 큐의 합이 2로 나누어 떨어지지 않는다면 정수를 반환할 수 없기에 -1 반환.
    if total_sum % 2 != 0:
        return -1
       
	
  # 1. 투 포인터로 queue1이 차지하는 연속 구간 [l ~ r]을 표현
    n = len(queue1)
    r = n - 1  
    l = 0  
    moves = 0 # 작업횟수
    
    q1 = deque(queue1) 
    q2 = deque(queue2)
    

    # 2. 현재 구간의 합이 목표치와 같아질 때까지 queue1 원소조작
    while current_sum != target_sum:
        if current_sum < target_sum: # queue1 원소의합이 target_sum 보다 작으면
            r += 1 # queue1의 영역 확장 (= 원소 append)
            if r == n * 2: # 예외처리
                return -1 
           
            val = q2.popleft() # 위에서 말한대로 큐에도 적용
            q1.append(val)  
            current_sum += val 
            
        else: # queue1 원소의 합이 target_sum 보다 클 땐
            val = q1.popleft() # queue1 범위 축소
            q2.append(val)
            current_sum -= val
            l += 1

        moves += 1 # 원소조작 이후에는 moves 1 증가시키기

    return moves # 3. 최종 moves 반환

느낀점

(1)

popleft() appendleft() 등 dequeue의 특징을 잘 살리지 못한 듯 해서 아쉽다.

(2)

AI 사용에 대한 생각을 더 해보게 되는 문제였다.

(1)의 아쉬움 때문에, 이를 보완해보고자 AI에게 이것을 풀게했고,
아래와 같은 풀이를 확인했다.

from collections import deque

def solution(queue1, queue2):
    q1 = deque(queue1)
    q2 = deque(queue2)

    sum1 = sum(q1)
    sum2 = sum(q2)
    total_sum = sum1 + sum2

    if total_sum % 2 != 0:
        return -1

    target = total_sum // 2
    moves = 0
    max_moves = len(queue1) * 4 # ?

    while moves <= max_moves:
        if sum1 == target:
            return moves

        if sum1 > target:
            val = q1.popleft()
            sum1 -= val
            q2.append(val)
        else:
            val = q2.popleft()
            sum1 += val
            q1.append(val)

        moves += 1

    return -1
1) 두 큐의 원소합이 같아질 때를 구한다.

2) 두 큐의 원소 이동 최대치는 한 큐의 4배이다. 이유는
① queue1에 있는 원소를 queue2로 모두 이동시키는 경우
② queue2 + queue1 모든 원소를 다시 queue1로 이동시키는 경우
③ queue2에 있는 원소를 queue1로 모두 이동시키는 경우 

3) 상한선까지 큐를 조작하며 조작 횟수 반환

이라고 한다...?

max_moves = len(queue1) * 4라는 코드가 이해되지 않았고,
심지어 4 대신 2와 3을 넣어도 프로그래머스에서는 정답 처리 된다.
??? AI에게 이유를 물어보았지만 여전히 명확한 근거를 이해하지는 못했다.

그니까 왜 충분히 결론이 난다고 생각하는건데?!!

이번 경험을 통해 뼈저리게 느낀 점은, AI에게 '해줘' 라고 말하면 코드가 뽑히지만,
내가 이해하지 못하는 코드를 그대로 가져다 쓰게 된다면 훗날 유지보수나 확장 과정에서 곤란해질 확률이 있을 것이다라는 것.

AI가 작성한 코드를 가져다 쓸 때는 반드시 이를 이해하고 검증하는 과정이 필요하다는 것을 다시 한번 느꼈다.

탄탄한 기본기를 바탕으로 어떤 코드든 이해하고 검증할 수 있어야만, 이를 응용해 새로운 것을 만들어 낼 수 있을 것이다.

새로운 것을 만들 수 있는 사람이 되고 싶다면

기본기에 충실하자.

profile
양치기소녀

0개의 댓글