k를 구하는 이분 탐색인 것 같다.
따라서 mid값이 바뀔 때마다 바나나를 전부 먹을 수 있는지 체크하는 로직이 있어야 함
다만 문제는 start가 몇이고 end가 몇인가.. ?
start는 당연히 1일거고, end는 piles에서 가장 큰 값으로 한 번 줘보는게 좋겠다.
그래서 풀어봤는데.. 통과는 하는데 런타임과 메모리가 마음에 안든다.
성능에 이상을 주는 부분은 없는거같은데.. 최적화를 어떻게 할 수 있을까?
(최적화 전 코드)
class Solution {
public int minEatingSpeed(int[] piles, int h) {
int start = 1;
int end = 0;
for (int p : piles) {
end = Math.max(end, p);
}
while (start <= end) {
int mid = start + (end - start) / 2;
int result = canEat(piles, h, mid);
if (result == 1) {
end = mid - 1;
} else {
start = mid + 1;
}
}
return start;
}
private int canEat(int[] piles, int h, int k) {
int time = 0;
for (int i=0; i<piles.length; i++) {
// 이미 못하는 걸 알기 때문에 더 수행할 필요 없음
if (time > h) {
break;
}
if (piles[i] <= k) {
time++;
} else {
time += Math.ceil((double) piles[i] / k);
}
}
return time <= h ? 1 : -1;
}
}
(최적화)
(pile + k - 1) / k
)start < end
로 고정해 두고,end = mid
와 start = mid + 1
하면 항상 결과값이 start에 남게 됨class Solution {
public int minEatingSpeed(int[] piles, int h) {
int start = 1;
int end = 0;
for (int p : piles) {
end = Math.max(end, p);
}
while (start < end) {
int mid = start + (end - start) / 2;
if (canEat(piles, h, mid)) {
end = mid;
} else {
start = mid + 1;
}
}
return start;
}
private boolean canEat(int[] piles, int h, int k) {
int time = 0;
for (int pile : piles) {
time += (pile + k - 1) / k;
if (time > h) return false;
}
return true;
}
}