[JAVA] 프로그래머스 두 큐 합 같게 만들기

John·2022년 11월 7일
1

코테 메모🌼

목록 보기
12/28
post-thumbnail

문제 설명

레벨 2

길이가 같은 두 개의 큐가 주어집니다. 하나의 큐를 골라 원소를 추출(pop)하고, 추출된 원소를 다른 큐에 집어넣는(insert) 작업을 통해 각 큐의 원소 합이 같도록 만들려고 합니다. 이때 필요한 작업의 최소 횟수를 구하고자 합니다. 한 번의 pop과 한 번의 insert를 합쳐서 작업을 1회 수행한 것으로 간주합니다.

큐는 먼저 집어넣은 원소가 먼저 나오는 구조입니다. 이 문제에서는 큐를 배열로 표현하며, 원소가 배열 앞쪽에 있을수록 먼저 집어넣은 원소임을 의미합니다. 즉, pop을 하면 배열의 첫 번째 원소가 추출되며, insert를 하면 배열의 끝에 원소가 추가됩니다. 예를 들어 큐 [1, 2, 3, 4]가 주어졌을 때, pop을 하면 맨 앞에 있는 원소 1이 추출되어 [2, 3, 4]가 되며, 이어서 5를 insert하면 [2, 3, 4, 5]가 됩니다.

다음은 두 큐를 나타내는 예시입니다.

queue1 = [3, 2, 7, 2]
queue2 = [4, 6, 5, 1]

두 큐에 담긴 모든 원소의 합은 30입니다. 따라서, 각 큐의 합을 15로 만들어야 합니다. 예를 들어, 다음과 같이 2가지 방법이 있습니다.

queue2의 4, 6, 5를 순서대로 추출하여 queue1에 추가한 뒤, queue1의 3, 2, 7, 2를 순서대로 추출하여 queue2에 추가합니다. 그 결과 queue1은 [4, 6, 5], queue2는 [1, 3, 2, 7, 2]가 되며, 각 큐의 원소 합은 15로 같습니다. 이 방법은 작업을 7번 수행합니다.
queue1에서 3을 추출하여 queue2에 추가합니다. 그리고 queue2에서 4를 추출하여 queue1에 추가합니다. 그 결과 queue1은 [2, 7, 2, 4], queue2는 [6, 5, 1, 3]가 되며, 각 큐의 원소 합은 15로 같습니다. 이 방법은 작업을 2번만 수행하며, 이보다 적은 횟수로 목표를 달성할 수 없습니다.
따라서 각 큐의 원소 합을 같게 만들기 위해 필요한 작업의 최소 횟수는 2입니다.

길이가 같은 두 개의 큐를 나타내는 정수 배열 queue1, queue2가 매개변수로 주어집니다. 각 큐의 원소 합을 같게 만들기 위해 필요한 작업의 최소 횟수를 return 하도록 solution 함수를 완성해주세요. 단, 어떤 방법으로도 각 큐의 원소 합을 같게 만들 수 없는 경우, -1을 return 해주세요.


제한사항

  • 1 ≤ queue1의 길이 = queue2의 길이 ≤ 300,000
  • 1 ≤ queue1의 원소, queue2의 원소 ≤ 109
  • 주의: 언어에 따라 합 계산 과정 중 산술 오버플로우 발생 가능성이 있으므로 long type 고려가 필요합니다.

입출력 형식

queue1queue2result
[3, 2, 7, 2][4, 6, 5, 1]2
[1, 2, 1, 2][1, 10, 1, 2]7

풀이

package programmers;

import java.util.LinkedList;
import java.util.Queue;

public class 두큐합같게만들기 {

	public static void main(String[] args) {
		
		// result = 2
		int[] queue1 = {3, 2, 7, 2};
		int[] queue2 = {4, 6, 5, 1};
		
		// result = 9
		int[] a1 = {3, 3, 3, 3};
		int[] b1 = {3, 3, 21, 3};
		
		System.out.println(solution(queue1, queue2));
		System.out.println(solution(a1, b1));

	}
	
	/**
	 * @date 2022-11-07
	 * @TODO 그리디 알고리즘 공부 필요 
	 * 
	 * 1 ≤ queue1의 길이 = queue2의 길이 ≤ 300,000
	 * 1 ≤ queue1의 원소, queue2의 원소 ≤ 10^9
	 * 주의: 언어에 따라 합 계산 과정 중 산술 오버플로우 발생 가능성이 있으므로 long type 고려가 필요합니다.
	 * 
	 * @param queue1, queue2 길이가 같은 두 개의 큐를 나타내는 정수 배열
	 * @return 각 큐의 원소 합을 같게 만들기 위해 필요한 작업의 최소 횟수, 단 어떤 방법으로도 각 큐의 원소 합을 같게 만들 수 없는 경우, -1
	 */
	public static int solution(int[] queue1, int[] queue2) {
		

		long sum = 0;		
		long half = 0;		
		int maxNumberOfQueue1 = 0;		
		int maxNumberOfQueue2 = 0;		
		long sumOfQueue1 = 0;	
		long sumOfQueue2 = 0;	
		int answer = 0;		
		
		Queue<Integer> q1 = new LinkedList<>();	
		Queue<Integer> q2 = new LinkedList<>();	
		
		for(int queue : queue1) {
			q1.add(queue);
			if(maxNumberOfQueue1 < queue) {
				maxNumberOfQueue1 = queue;
			}
			sumOfQueue1 = sumOfQueue1 + queue;
			sum = sum + queue; 
		}
		
		for(int queue : queue2) {
			q2.add(queue);
			if(maxNumberOfQueue2 < queue) {
				maxNumberOfQueue2 = queue;
			}
			sumOfQueue2 = sumOfQueue2 + queue;
			sum = sum + queue; 
		}
		
		half = sum / 2;
		
		for(int i=0; i<3*queue1.length; i++) {
			if(sumOfQueue1 == sumOfQueue2) {
				return answer;
			}
			
			else if(sumOfQueue1 < sumOfQueue2) {
				q1.add(q2.peek());
				sumOfQueue2 = sumOfQueue2 - q2.peek();
				sumOfQueue1 = sumOfQueue1 + q2.poll();
				answer = answer + 1;
			}
			
			else if(sumOfQueue1 > sumOfQueue2) {
				q2.add(q1.peek());
				sumOfQueue1 = sumOfQueue1 - q1.peek();
				sumOfQueue2 = sumOfQueue2 + q1.poll();
				answer = answer + 1;
			}
		}
		
		if(sum%2 == 1 || half < maxNumberOfQueue1 || half < maxNumberOfQueue2) {
			return -1;
		}
		
        return -1;
    }

}

끄적끄적


결과


느낀점

코드를 여러 번 수정한 끝에 통과했다.

첫번째

합 계산 과정 중 산술 오버플로우 발생 가능성이 있으므로 long type 고려가 필요합니다.

위 부분을 고려하지 않아 합계 관련 변수의 타입을 수정했다.


두번째

for(int i=0; i<3*queue1.length; i++) {
			if(sumOfQueue1 == sumOfQueue2) {
				return answer;
			}
            
 ...

반복문의 범위를 2*queue1.length로 생각했다.

// result = 9
int[] a1 = {3, 3, 3, 3};
int[] b1 = {3, 3, 21, 3};

친절하신 분께서 테스트케이스를 공유해주셔서 범위를 여유롭게 수정했다.


글로 써보는게 편해서 고려해야 할 사항을 미리 정리 후 코드를 작성함에도 이렇게 빠트리는게 많다.
심지어 첫 번째는 제한사항에 적어져 있었다.

꼼꼼히 확인하고 문제풀자..!😂

profile
기록을 습관으로

0개의 댓글