class MaxHeap {
constructor(){
this.heap = [null];
this.sum = 0;
this.length = 0;
}
push(value){
this.heap.push(value);
let current = this.heap.length-1;
let parent = Math.floor(current / 2);
while(parent !== 0 && this.heap[parent] < value){
const temp = this.heap[parent];
this.heap[parent] = value;
this.heap[current] = temp;
current = parent;
parent = Math.floor(current / 2);
}
this.sum += value;
this.length += 1;
}
pop(){
if(this.heap.length === 2) return this.heap.pop();
const returnValue = this.heap[1];
this.heap[1] = this.heap.pop();
let current = 1;
let left = 2;
let right = 3;
while(
this.heap[current] < this.heap[left] || this.heap[current] < this.heap[right]
){
if(this.heap[left] < this.heap[right]){
const temp = this.heap[current];
this.heap[current] = this.heap[right];
this.heap[right] = temp;
current = right
} else {
const temp = this.heap[current];
this.heap[current] = this.heap[left];
this.heap[left] = temp ;
current = left;
}
left = current * 2;
right = current * 2 + 1;
}
this.sum -= returnValue;
this.length -= 1;
return returnValue;
}
};
function solution(n, k, enemy) {
let count = 0;
const heap = new MaxHeap();
for(const e of enemy){
if(heap.sum + e <= n){
heap.push(e);
} else {
if(k === 0) return heap.length + count;
const value = heap.heap[1] === undefined ? 0 : heap.heap[1];
if(value <= e) {
k -= 1, count += 1;
continue;
} else {
k -= 1, count += 1;
heap.pop();
heap.push(e);
};
};
};
return count + heap.length;
};
파라메트릭 서치로도 가능할까 싶었던 문제지만 시도를 하지 않았었는데, 파라메트릭서치로 푼 분들이 있었다.
방법은 파라메트릭 서치로 mid만큼 자르기 => 매번 내림차순으로 검사 => k만큼 클리어 했다 생각하고 나머지 합을 검사. => 만족하는 최소의 조건을 찾을때까지 검사.
물론 효율성적인 측면에서는 아슬아슬하지만, (매 탐색마다 정렬과 합계를 위한 시간복잡도가 요구된다) 흥미로운 풀이인 것 같아서 참고했다.
const check = (n, k, mid, enemy) => {
if (mid <= k) return true;
let t = enemy.slice(0, mid).sort((a, b) => b - a);
let sum = 0;
for (let i = k; i < t.length; i++) {
sum += t[i];
if (sum > n) return false;
}
return true;
}
function solution(n, k, enemy) {
let left = 0, right = enemy.length;
while(left <= right) {
let mid = Math.floor((left+right) / 2);
if(check(n, k, mid, enemy)) left = mid+1;
else right = mid - 1;
}
return left - 1;
}