1. 문제 분석
두 개의 큐가 주어지고, 한 큐에서 원소를 빼서 다른 큐에 추가하는 방식으로 두 큐의 원소 합을 같게 만들고자 한다. 최소 작업 횟수를 구하는 것이 목표이며, 어떤 방법으로도 같게 만들 수 없다면 -1
을 반환해야 한다.
핵심 포인트
- 총합이 홀수이면 불가능
- 두 큐의 원소 합이 홀수이면 절대 같은 값으로 만들 수 없다.
- 투 포인터 (Two Pointers) 활용
- 큐의 원소를 이동하며 합을 맞추는 방식이므로, 투 포인터 또는 슬라이딩 윈도우 기법을 활용할 수 있다.
- 최대 이동 횟수 제한
- 한 큐의 길이가
n
일 때, 최악의 경우3 * n
번의 이동 내에서 해결할 수 있어야 한다.
- 한 큐의 길이가
2. 해결 방법
- 초기 설정
- 두 큐의 합을 각각 계산한다.
sum1
,sum2
의 합이 홀수이면-1
반환.- 두 큐를
LinkedList
(큐)로 변환하여 사용한다.
- 투 포인터 (슬라이딩 윈도우) 방식 적용
sum1
이sum2
보다 크면queue1
에서 pop한 후queue2
에 삽입.sum2
이sum1
보다 크면queue2
에서 pop한 후queue1
에 삽입.- 두 큐의 합이 같아지면 반복 종료.
- 최대
3 * n
번의 연산을 초과하면-1
반환.
3. 코드 구현
import java.util.*;
class Solution {
public int solution(int[] queue1, int[] queue2) {
long sum1 = 0, sum2 = 0;
Queue<Integer> q1 = new LinkedList<>();
Queue<Integer> q2 = new LinkedList<>();
// 초기 합 계산 및 큐에 삽입
for (int i = 0; i < queue1.length; i++) {
sum1 += queue1[i];
sum2 += queue2[i];
q1.add(queue1[i]);
q2.add(queue2[i]);
}
// 총합이 홀수이면 불가능
if ((sum1 + sum2) % 2 != 0) return -1;
long target = (sum1 + sum2) / 2;
int cnt = 0, limit = queue1.length * 3; // 최대 이동 가능 횟수 제한
while (cnt < limit) {
if (sum1 == target) return cnt; // 종료 조건
if (sum1 > target) { // q1에서 pop 후 q2에 삽입
int num = q1.poll();
sum1 -= num;
sum2 += num;
q2.add(num);
} else { // q2에서 pop 후 q1에 삽입
int num = q2.poll();
sum2 -= num;
sum1 += num;
q1.add(num);
}
cnt++;
}
return -1; // 불가능한 경우
}
}
4. 코드 분석
1. 입력 처리 및 초기화
long sum1 = 0, sum2 = 0;
Queue<Integer> q1 = new LinkedList<>();
Queue<Integer> q2 = new LinkedList<>();
for (int i = 0; i < queue1.length; i++) {
sum1 += queue1[i];
sum2 += queue2[i];
q1.add(queue1[i]);
q2.add(queue2[i]);
}
- 두 큐의 합을
sum1
,sum2
에 저장. queue1
과queue2
를LinkedList
큐로 변환.
2. 불가능한 경우 확인
if ((sum1 + sum2) % 2 != 0) return -1;
- 전체 합이 홀수이면 두 큐의 합이 같아질 수 없으므로
-1
반환.
3. 투 포인터 방식 적용
long target = (sum1 + sum2) / 2;
int cnt = 0, limit = queue1.length * 3;
while (cnt < limit) {
if (sum1 == target) return cnt; // 목표 달성 시 종료
if (sum1 > target) { // sum1이 크면 q1에서 pop 후 q2에 삽입
int num = q1.poll();
sum1 -= num;
sum2 += num;
q2.add(num);
} else { // sum2가 크면 q2에서 pop 후 q1에 삽입
int num = q2.poll();
sum2 -= num;
sum1 += num;
q1.add(num);
}
cnt++;
}
sum1 > target
이면queue1
에서 pop하여queue2
에 삽입.sum2 > target
이면queue2
에서 pop하여queue1
에 삽입.cnt
가3 * n
을 초과하면-1
반환.
5. 개선할 점 및 대체 방법
- Deque 사용
LinkedList
보다ArrayDeque
이poll()
연산에서 더 빠르므로 변경 가능.
- 배열을 사용한 포인터 접근 방식
- 큐를 두 개의 포인터로 관리하여
poll()
을 없애고start
인덱스를 조정하는 방식 사용 가능.
- 큐를 두 개의 포인터로 관리하여
- 특정 값이 너무 커서 해결이 불가능한 경우 미리 검사
- 두 큐의 최대값이 목표 값보다 크면
-1
을 즉시 반환할 수 있다.
- 두 큐의 최대값이 목표 값보다 크면
'코딩테스트 > 프로그래머스' 카테고리의 다른 글
[프로그래머스] k진수에서 소수 개수 구하기 (1) | 2025.03.20 |
---|---|
[프로그래머스] 택배 배달과 수거하기 풀이 및 코드 분석 (0) | 2025.03.20 |
[프로그래머스] 이모티콘 할인행사 풀이 및 코드 분석 (0) | 2025.03.20 |
[프로그래머스] 도넛과 막대 그래프 풀이 및 코드 분석 (0) | 2025.03.20 |