프로그래머스 Level 4 무지의먹방라이브
무지의먹방라이브 (프로그래머스 Level 4)
https://school.programmers.co.kr/learn/courses/30/lessons/42891
까다로운 문제였다
처음에는 단순 queue를 사용하여 하나씩 빼주는 방식을 사용하였으나
시간초과가 발생하였다
그렇기에 로직을 수정하여 ‘우선순위 큐’를 2번 사용하는 방식으로 수정하여 문제를 해결하였다
풀이의 요점은
- 전체값의 합이 k보다 작거나 같다면,
장애 타이밍 전에 모든 음식을 먹었으므로 -1 - fool 벡터의 최솟값 * 벡터 사이즈 가 k보다 작다면
별도의 요소를 제거할 필요가 없으므로
k % fSize + 1 을 return - 이후 해당 값을 이용하여
‘남은 용량’이 적은 순으로 ‘우선순위 큐’를 생성하여
벡터 내의 ‘최솟값’을 갱신하여 다시 재적용
( checkM = (long long)(minV - prevM) * q.size())
k가 해당 수치보다 작다면
현재 요소 중 하나이다
그렇지 않다면 해당 수치만큼 k에서 빼주고
다음 큐로 - k가 checkM보다 작을 때,
‘원래’ 순서가 다시 필요하므로
원래 순서를 기준으로 우선순위 큐를 재조정
이후, k % q.size() 만큼 새로운 우선순위 큐에서 빼준후
남은 큐의 top에서 순서를 획득
꽤나 어려웠던 문제였기에 예시를 하나 들려고 한다
{4,2,3,6,7,1,5,8} , 27 인 경우 정답은 5가 되는데
먼저 1이 최솟값이므로
checkM 은 (1 - 0) * 8(큐 크기) = 8이 되고
이를 k에서 빼준다
k : 27 - 8 = 19
이후 원래 1이였던 요소가 ‘제거’ 되므로
큐 사이즈가 7이 되며
다시 k를 빼간다
k : 19 - 7 …
k : 12 - 6 …
k : 6 - 5 …
이 때까지 4까지 제거되고 k는 1이된다
현재 남은 수들은
{0,0,0,2,3,0,1,4}이며
이중 2인 4번째(정답은 +1 하여 5)가 되어야 한다
개인적으로 고민된 것이
우선순위 큐에서 ‘최솟값’을 빼기에 ‘마지막 순간’에
자동적으로 1,2,3,4 로 정렬되어 있는 것을
다시 원래 순서인 2,3,1,4 순으로 바꿔주어야 했던 점이며
이를 위하여 ‘우선순위 큐’를 하나 다시 파서
해당 큐에 집어넣은 후 빼주는 방식을 사용하였다
큐를 사용하면 되겠다는 대략적인 생각은 있었고
k를 저렇게 구하면 되겠다는 생각은 있었으나
시간 초과 후, 추가적으로 ‘우선순위 큐’를 생각했던 것 같다
어찌어찌 열심히 풀기는 하였지만, 실제로 이러한 문제가 주어졌을 때
짧은 시간 내에 풀 수 있을지는 자신이 없다
Code
#include <vector>
#include<queue>
#include<algorithm>
using namespace std;
int solution(vector<int> food_times, long long k) {
long long answer = -1;
long long minV = food_times[0];
long long sumV = 0;
const int fSize = food_times.size();
for (int f : food_times)
{
sumV += f;
if (f < minV)
minV = f;
}
long long checkM = minV * fSize;
if (sumV <= k)
{
return -1;
}
if (checkM >= k)
{
answer = (k % fSize) + 1;
return answer;
}
k -= checkM;
struct cmp {
bool operator()(const pair<long long, long long>& a, const pair<long long, long long>& b) {
if (a.second == b.second)
return a.first > b.first;
return a.second > b.second;
}
};
priority_queue<pair<long long, long long>, vector<pair<long long, long long>>, cmp > q;
for (int i = 0; i < fSize; i++)
{
if (food_times[i] - minV <= 0)
continue;
q.push({ i + 1,food_times[i] - minV });
}
minV = 0;
while (q.empty() == false)
{
auto p = q.top();
int prevM = minV;
minV = p.second;
checkM = (long long)(minV - prevM) * q.size(); // 이전과 값이 같았다면 여기서 0 나오므로 일단 중복은 상관 x
if (k < checkM)
{
int idx = k % q.size();
// 이 시점에서 first 기준으로 다시 정렬이 필요함
priority_queue<pair<long long, long long>, vector<pair<long long, long long>>, greater<pair<long long, long long>>> pq;
while (q.empty() == false)
{
pq.push(q.top());
q.pop();
}
while (idx > 0)
{
pq.pop();
idx--;
}
answer = pq.top().first;
return answer;
}
else
{
k -= checkM;
}
q.pop();
}
return answer;
}
댓글남기기