You are given a 0-indexed integer array piles, where piles[i] represents the number of stones in the ith pile, and an integer k. You should apply the following operation exactlyk times:
Choose any piles[i] and removefloor(piles[i] / 2) stones from it.
Notice that you can apply the operation on the same pile more than once.
Return the minimum possible total number of stones remaining after applying thekoperations.
floor(x) is the greatest integer that is smaller than or equal to x (i.e., rounds x down).
Input:
piles = [5,4,9], k = 2
Output:
12
Explanation: Steps of a possible scenario are:
- Apply the operation on pile 2. The resulting piles are [5,4,5].
- Apply the operation on pile 0. The resulting piles are [3,4,5].
The total number of stones in [3,4,5] is 12.
Example 2:
1
2
3
4
5
6
7
8
9
Input:
piles = [4,3,6,7], k = 3
Output:
12
Explanation: Steps of a possible scenario are:
- Apply the operation on pile 2. The resulting piles are [4,3,3,7].
- Apply the operation on pile 3. The resulting piles are [4,3,3,4].
- Apply the operation on pile 0. The resulting piles are [2,3,3,4].
The total number of stones in [2,3,3,4] is 12.
To minimize the total number of stones, we should always remove stones from the largest pile, as this reduces the total the most in each operation. Using a max heap allows us to efficiently select and update the largest pile at each step.
classSolution {
public:int minStoneSum(vector<int>& piles, int k) {
priority_queue<int> pq(piles.begin(), piles.end());
while (k--) {
int x = pq.top(); pq.pop();
x -= x /2;
pq.push(x);
}
int ans =0;
while (!pq.empty()) {
ans += pq.top(); pq.pop();
}
return ans;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
funcminStoneSum(piles []int, kint) int {
h:=&IntHeap{}
heap.Init(h)
for_, v:=rangepiles {
heap.Push(h, -v)
}
fori:=0; i < k; i++ {
x:=-heap.Pop(h).(int)
x-=x/2heap.Push(h, -x)
}
ans:=0forh.Len() > 0 {
ans+=-heap.Pop(h).(int)
}
returnans}
// type IntHeap and heap interface methods omitted for brevity
1
2
3
4
5
6
7
8
9
10
11
12
13
classSolution {
publicintminStoneSum(int[] piles, int k) {
PriorityQueue<Integer> pq =new PriorityQueue<>(Collections.reverseOrder());
for (int p : piles) pq.add(p);
while (k--> 0) {
int x = pq.poll();
pq.add(x - x / 2);
}
int ans = 0;
while (!pq.isEmpty()) ans += pq.poll();
return ans;
}
}
1
2
3
4
5
6
7
8
9
10
11
classSolution {
funminStoneSum(piles: IntArray, k: Int): Int {
val pq = PriorityQueue<Int>(compareByDescending { it })
for (p in piles) pq.add(p)
repeat(k) {
val x = pq.poll()
pq.add(x - x / 2)
}
return pq.sum()
}
}
1
2
3
4
5
6
7
8
9
10
import heapq
classSolution:
defminStoneSum(self, piles: list[int], k: int) -> int:
h = [-x for x in piles]
heapq.heapify(h)
for _ in range(k):
x =-heapq.heappop(h)
x -= x //2 heapq.heappush(h, -x)
return-sum(h)
1
2
3
4
5
6
7
8
9
10
11
12
impl Solution {
pubfnmin_stone_sum(piles: Vec<i32>, k: i32) -> i32 {
use std::collections::BinaryHeap;
letmut pq = BinaryHeap::from(piles);
for _ in0..k {
letmut x = pq.pop().unwrap();
x -= x /2;
pq.push(x);
}
pq.iter().sum()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
classSolution {
minStoneSum(piles: number[], k: number):number {
consth=newMaxPriorityQueue<number>({priority: x=>x});
for (constpofpiles) h.enqueue(p);
for (leti=0; i<k; i++) {
letx=h.dequeue().element;
x-= Math.floor(x/2);
h.enqueue(x);
}
letans=0;
while (!h.isEmpty()) ans+=h.dequeue().element;
returnans;
}
}