반응형
문제 : https://programmers.co.kr/learn/courses/30/lessons/43237
서론
이진탐색 문제인데,
뭔가 M/budgets.size()를 이용해서 풀 수 있을것 같아서 먼저 시도했다가 실패하고 이진탐색으로 해결
풀이
1번 조건이 해당되는지 확인 후에
2번 조건은 이진탐색으로 해결한다.
이때 이진탐색할 배열은 [1,2,3,4,.....m-1,m]이다.
반복되는 이진탐색에서 mid의 값은 정수상한액이며 2번 조건에 따라 정수상한액으로 총 예산을 계산한다.
long long cal(int mid, vector<int> &budgets){
long long sum = 0;
for(auto i : budgets){
if(mid<i) sum +=mid;
else sum += i;
}
return sum;
}
총 예산액이 M과 동일하면 mid는 정답이며 이진탐색을 빠져나온다.
총 예산액이 M보다 크거나 작으면 이진탐색을 계속해준다.
디버깅
1. 총 예산액이 mid와 동일한 경우가 없을때
총 예산액이 mid와 동일한 경우가 없을 수 있다. 정답은 mid의 최대값을 찾는 것이므로 반복문에서 총 예산액이 M보다 작거나 같을때는 answer값을 mid로 갱신해주고 클때는 갱신하지 않아야 한다.
클때도 갱신하게 되면 총 예산액이 M을 초과했을때 mid값이 answer가 된 후 반복문의 start<=end 조건을 만족하지 못해서 answer가 그대로 출력될 수 있다.
반례
budgets = [1,2,3,4], M = 8;
정답2, 오답3
수정 전
while (start <= end) {
mid = (start + end) / 2;
sum = cal(mid, budgets);
//cout<<mid<<" "<<sum<<endl;
answer = mid;
if (sum == M) break;
else if (sum < M) start = mid + 1;
else if (sum > M) end = mid - 1;
}
수정 후
while (start <= end) {
mid = (start + end) / 2;
sum = cal(mid, budgets);
//cout<<mid<<" "<<sum<<endl;
if (sum == M) {
answer = mid;
break;
}
else if (sum < M) {
answer = mid;
start = mid + 1;
}
else if (sum > M) end = mid - 1;
}
2. 총 예산액의 자료형
총 예산액의 자료형을 int로 만들면 효율성테스트에서 실패가 뜬다.
long long으로 수정해야한다.
구현
// c++
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
long long cal(int x, vector<int> &budgets){
long long sum = 0;
for(auto i : budgets){
if(x<i) sum +=x;
else sum += i;
}
return sum;
}
int solution(vector<int> budgets, int M) {
int answer = 0;
long long sum = 0;
// 1번
for(auto i : budgets){
sum += i;
answer = max(answer, i);
}
if(sum <=M) return answer;
else answer = 0;
// 2번
int start = 1;
int end = M;
int mid = (start+end)/2;
while(start<=end){
mid = (start+end)/2;
sum = cal(mid, budgets);
//cout<<mid<<" "<<sum<<endl;
if (sum == M) {
answer = mid;
break;
}
else if(sum<M) {
answer = mid;
start = mid +1;
}
else if(sum>M) end = mid - 1;
}
return answer;
}
최근댓글