안녕하세요! 테크지니어22입니다.
오늘은 프로그래머스 알고리즘 두 큐 합 같게 만들기 를 풀어보도록 하겠습니다.
https://school.programmers.co.kr/learn/courses/30/lessons/118667
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
[문제 접근]
저는 문제를 읽으면서 이런 식으로 풀면되지 않을까? 라는 그리디 알고리즘으로 접근했습니다.
queue1의 합이 == 총합 / 2 이면 정답
queue1의 합이 > 총합 / 2 이면 queue1에서 pop하고 queue2에 넣기.
queue1의 합이 < 총합 / 2 이면 queue2에서 pop하고 queue1에 넣기.
그리고 이를 계속 반복했습니다. 멈추는 조건이 필요했습니다.
큐가 비어있을 경우 멈추어야 하고 한 가지 조건이 더 있습니다.
저는 이때 한 멈추는 조건을 어렴풋이 고려해야하는 것을 알고 있었는데, 예외 케이스를 떠올리기가 힘들어서 설마 이거로 틀리겠어?하고 넘어갔었습니다. 근데 이 안일한 생각이 몇 시간을 고민하게 했습니다. 프로그래머스는 시간 초과에 무한루프도 포함하는 것도 덤으로 알았습니다. 그 조건은 바로 queue1과 queue2의 길이 중 더 큰 길이의 *2배보다 pop의 개수가 많을 때입니다.
queue1과 queue2를 모두 한 바퀴 지나갔고 다시 처음 상태로 되돌아왔을 때를 고려해야합니다.
[풀이 전략]
deque를 이용하여 문제접근의 내용을 코드로 바꾸었습니다.
[코드]
#include <string>
#include <vector>
#include <numeric>
#include <queue>
using namespace std;
typedef long long ll ;
ll q1_sum ;
ll q2_sum ;
ll val ;
deque<ll> q1;
deque<ll> q2 ;
int solution(vector<int> queue1, vector<int> queue2) {
int answer = 0;
for(auto v : queue1) {
q1_sum += v;
q1.push_back(v);
}
for(auto v : queue2) {
q2_sum += v;
q2.push_back(v);
}
val = (q1_sum + q2_sum)/2 ;
while(1) {
if(q1_sum == val) break;
if(q1.empty() || q2.empty()) {answer = -1 ; break ; }
int tot_size = q1.size()+q2.size();
if(answer > tot_size*2 ) {answer = -1 ; break ; } // tot_size *2배만큼 돌아야 원래순서대로 돌아감.
else if(q1_sum > val) {
ll tmp = q1.front();
q1_sum -= tmp ;
q2_sum += tmp ;
q2.push_back(tmp); q1.pop_front();
answer++;
} else {
ll tmp = q2.front();
q1_sum += tmp ;
q2_sum -= tmp ;
q1.push_back(tmp); q2.pop_front();
answer++;
}
}
return answer;
}
추가 풀이 방법 - 투 포인터
#include <string>
#include <vector>
#include <numeric>
#include <iostream>
#include <queue>
using namespace std;
typedef long long ll ;
ll q1_sum ;
ll q2_sum ;
ll val ;
int st;
int en ;
int solution(vector<int> queue1, vector<int> queue2) {
int answer = 0;
int q1_size = queue1.size();
int q2_size = queue2.size();
int tot_size = q1_size + q2_size;
st = 0;
en = q1_size-1;
q1_sum = accumulate(queue1.begin(),queue1.end(),0);
q2_sum = accumulate(queue2.begin(),queue2.end(),0);
ll tot_sum = q1_sum + q2_sum ;
ll val = tot_sum / 2 ;
queue1.insert(queue1.end(), queue2.begin(),queue2.end());
while(1) {
if(st > en || answer > tot_size*2) {answer = -1 ; break;} // tot_size *2배만큼 돌아야 원래순서대로 돌아감.
if(q1_sum == val) break;
else if( q1_sum > val) {
q1_sum -= queue1[st % tot_size];
st++; answer++;
}
else {
en++; answer++;
q1_sum += queue1[en % tot_size];
}
}
return answer;
}
[배울 점]
- 어렴풋이 고려해야한다는 생각이 들면 넘어가지말고 반례 케이스를 계속 고민하기 -> 코드구현보다 알고리즘 모델링이 더 중요
'알고리즘 > 프로그래머스' 카테고리의 다른 글
[프로그래머스/C++] 알고리즘 - 양궁대회 (0) | 2024.05.23 |
---|---|
[프로그래머스/C++] 알고리즘 - 도넛과 막대 그래프 (0) | 2024.05.16 |
[프로그래머스/C++] 알고리즘 - 주사위 고르기 (0) | 2024.05.12 |
[프로그래머스/C++] 알고리즘 - 순위 검색 (0) | 2024.05.05 |
[프로그래머스/C++] 알고리즘 - 택배 배달과 수거하기 (2) | 2024.04.30 |