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


잦은 함수 사용으로 삽질하던 기억이 남아서 작성하는 포스트

정답제출코드


#include <string>
#include <vector>
#include <iostream>
#include <queue>

using namespace std;


// 큐 형태의 큐 원소 합
long long que_sum(queue<int> queue)
{
    long long return_sum = 0;
    for (int i = 0; i < queue.size(); ++i)
    {
        return_sum += queue.front();
        
        // 더하고 난 뒤에 맨 뒤로 보내기.
        queue.push(queue.front());
        queue.pop();
    }
    
    return return_sum;
}

int solution(vector<int> queue1, vector<int> queue2) {
    
    long long queue1_sum = 0, queue2_sum = 0;
    
    // 큐 선언 및 큐 형성
    queue<int> q1, q2;
    
    // 길이가 같은 두개의 큐의 길이 미리 저장.
    int queue_size = queue1.size();
    
    
    for (int i = 0; i < queue_size; ++i)
    {
        q1.push(queue1[i]);
        q2.push(queue2[i]);
    }
    

    queue1_sum = que_sum(q1);
    queue2_sum = que_sum(q2);
    
    long long queue_sum = (queue1_sum + queue2_sum);
    
    // 홀수라면 두 큐의 합이 같아지지 않음.
    // -1을 리턴한다.
    if (queue_sum % 2 == 1)
        return -1;
    
    queue_sum /= 2;
    
    // 두 큐를 순회하며 목표 값보다 큰 값이 있는지 확인한다.
    // 큰 값이 있다면 절대 만들 수 없으므로 -1을 반환해야한다.
    for (int i = 0; i < queue_size; ++i)
    {
        int q1_cur = q1.front();
        int q2_cur = q2.front();
        
        if (q1_cur > queue_sum || q2_cur > queue_sum)
            return -1;
        
        else
        {
            q1.push(q1_cur);
            q1.pop();
            
            q2.push(q2_cur);
            q2.pop();
        }
    }
    
    // 논리 : 합이 더 큰 쪽의 큐에 있는 원소를 옮긴다.
    
    int count = 0;
    
    while(true)
    {   
        
        if (queue2_sum > queue1_sum)
        {
            int q2_front = q2.front();
            
            queue2_sum -= q2_front;
            queue1_sum += q2_front;
            q1.push(q2_front);
            q2.pop();

            count++;
        }
        
        else if (queue1_sum > queue2_sum)
        {
            int q1_front = q1.front();
            
            queue1_sum -= q1_front;
            queue2_sum += q1_front;
            
            q2.push(q1_front);
            q1.pop();
            count++;
        }
        
        else if (queue1_sum == queue2_sum)
        {
            return count;
        }
        
        // 큐를 여러번 순환시켰는데 방법이 안나오는 경우 -1 리턴
        // 4 곱하기인 이유는 전체 배열의 길이는 2 * queue_size이고
        // 전부 한번씩 회전시키면 4 * queue_size가 되므로.
        if (count > 4 * queue_size)
            return -1;
    }
}


소스코드 설명


  • 큐 두개를 새로 만들어서 벡터의 원소를 각각 새로 만든 두 큐에 넣음.

  • 두 합이 홀수인 경우 그냥 -1을 반환한다.

  • 두 합을 2로 나눈 수 보다 큰 수가 큐 안에 있을 경우 절대 조건이 성립할 수 없으므로 이 역시 -1을 반환한다.

  • 두 큐 중에서 합이 더 큰 큐에 있는 원소를 다른 큐로 옮긴다. 이를 반복한다.


삽질한 내용


아래는 내가 삽질했던 코드이다.

#include <string>
#include <vector>
#include <iostream>

using namespace std;

long long q_sum(vector<int> queue)
{
    long long return_sum = 0;
    for (int i = 0; i < queue.size(); ++i)
    {
        return_sum += queue[i];
    }
    
    return return_sum;
}

int solution(vector<int> queue1, vector<int> queue2) {
    
    long long queue1_sum = 0, queue2_sum = 0;
    
    // 길이가 같은 두개의 큐의 길이 미리 저장.
    int queue_size = queue1.size();
    
    queue1_sum = q_sum(queue1);
    queue2_sum = q_sum(queue2);
    
    long long queue_sum = queue1_sum + queue2_sum;
    
    // 같은 수의 합 저장
    queue_sum /= 2;
    
    // 두 큐를 순회하며 목표 값보다 큰 값이 있는지 확인한다.
    // 큰 값이 있다면 절대 만들 수 없으므로 -1을 반환해야한다.
    for (int i = 0; i < queue_size; ++i)
    {
        if (queue1[i] > queue_sum || queue2[i] > queue_sum)
            return -1;
    }


    // 논리 : 합이 더 큰 쪽의 큐에 있는 원소를 옮긴다.
    
    int count = 0;
    
    while(true)
    {   
        queue2_sum = q_sum(queue2);
        queue1_sum = q_sum(queue1);
        
        if (queue2_sum > queue1_sum)
        {
            queue1.push_back(queue2[0]);
            queue2.erase(queue2.begin());
            count++;
        }
        
        else if (queue1_sum > queue2_sum)
        {
            queue2.push_back(queue1[0]);
            queue1.erase(queue1.begin());
            count++;
        }
        
        else if (queue1_sum == queue2_sum)
        {
            // 목표값을 달성했을 경우
            if (queue1_sum == queue_sum)
                return count;
        }
        
        // 큐를 여러번 순환시켰는데 방법이 안나오는 경우 -1 리턴
        // 4 곱하기인 이유는 최대 횟수를 넉넉하게 잡으려고.
        if (count > 4 * queue_size)
            return -1;
    }
}

요약을 하자면 처음엔 큐를 사용하지 않고 벡터만을 사용하였고, 무한 반복문을 돌 때 함수 사용을 너무 자주했다.

함수를 호출할 때 마다 시간이 걸린다는 것을 간과하여 큐1과 큐2에 있는 원소들의 합을 구할 때 마다 함수호출을 하여 시간을 지연시켰다.

그 결과 정답률이 63.6%에 그쳤다.

이 분의 글을 참조하여 합을 구하는 함수는 맨 처음에 한번만 사용하도록 하고,

함수를 이용해서가 아니라 큐의 원소를 옮길 때 변수를 조작하는 방식으로 반복문을 돌 때 마다 새로운 원소의 합을 구하도록 코드를 바꾸었고 그 결과 정답률 100%을 달성할 수 있었다.

반복문을 돌 때 함수 사용을 최대한 지양하도록 해야겠다.


© 2022.07. by Wookey_Kim

Powered by Hydejack v7.5.2