Remove Stones to Minimize the Total solution and explanation
9 more videos on this problem
Remove Stones to Minimize the Total (Google, Miscrosoft, Netflix, Meta) : Explanation ➕ Live CodingcodestorywithMIK · 16:50 · 10K views
`Leetcode 1962 Remove Stones to Minimize the Total | Coding Decoded SDE SheetCoding Decoded · 6:00 · 940 views
1962. Remove Stones to Minimize the Total (Leetcode Medium)Programming Live with Larry · 8:36 · 823 views
Leetcode 1962 Remove Stones to Minimize the Total - Java Solution Using Priority Queue ExplainedAlgorithmicIQ · 12:43 · 800 views
Daily Leetcode #1002: Dec 28, 2022 - 1962. Remove Stones to Minimize the TotalProgramming Live with Larry · 7:11 · 629 views
1962. Remove Stones to Minimize the TotalTech Adora by Nivedita · 7:59 · 609 views
1962 || Remove Stones to Minimize the Total || Leetcode Daily ChallengeCodeFreaks · 9:18 · 411 views
Remove Stones to Minimize the Total LeetCode - JavaCode with Katie · 14:46 · 313 views
Leetcode 1962 | Remove Stones to Minimize the Total | Streak 🔥| JAVACoding Spark · 11:22 · 225 views
Leetcode:1962. Remove Stones to Minimize the Total Daily Leetcode ProblemsCodenzyme · 5:17 · 198 views
The problem
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 exactly k 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 the k operations.
floor(x) is the greatest integer that is smaller than or equal to x (i.e., rounds x down).
Example 1:
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:
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.
Constraints:
1 <= piles.length <= 1051 <= piles[i] <= 1041 <= k <= 105
Approach overview
Problem Overview: You are given an array of stone piles. In each of the k operations, choose a pile and remove floor(pile / 2) stones from it. The goal is to minimize the total number of stones remaining after exactly k operations.
Approach 1: Use a Max-Heap for Efficient Pile Reduction (O(n + k log n) time, O(n) space)
This problem is naturally solved with a greedy strategy: always reduce the largest pile because removing half from a bigger pile decreases the total more. Store all piles in a max-heap so you can quickly access the current largest pile. For each of the k operations, extract the maximum element, remove floor(pile / 2), then push the updated pile back into the heap. Heap extraction and insertion both cost O(log n), so the total runtime becomes O(n + k log n) including heap construction.
The key insight is that the largest pile always provides the greatest reduction in the sum. Using a heap (priority queue) guarantees that this choice is efficient at every step. This approach works well even when k is large because each operation only touches the heap root.
Approach 2: Simulate Heap with Sorting (O(k n log n) time, O(1) extra space)
If a priority queue is unavailable in the language environment, you can simulate the greedy strategy by repeatedly sorting the array. In each operation, sort the piles in descending order, reduce the first element by floor(pile / 2), then continue to the next iteration. Sorting ensures the largest pile is always selected.
This approach still follows the same greedy idea but is less efficient because the array is re-sorted every time. Each iteration costs O(n log n), leading to O(k n log n) overall time. It is mainly useful in environments where implementing a heap is inconvenient or when input sizes are small.
Recommended for interviews: Interviewers typically expect the max-heap solution. Recognizing that the optimal move is always reducing the largest pile shows good greedy intuition, and implementing it with a priority queue demonstrates familiarity with efficient data structures. The sorting simulation helps explain the greedy reasoning, but the heap approach shows stronger algorithmic optimization skills.
Approach 1: Approach 1: Use a Max-Heap for Efficient Pile Reduction
The key idea of this approach is to use a max-heap (priority queue) to efficiently extract and update the largest pile each time. We repeatedly apply the operation on the largest pile, reducing it by floor(piles[i] / 2). Each time we remove the stones, we push the updated pile back into the max-heap for further operations until k operations are completed.
import heapq
def min_stone_sum(piles, k):
max_heap = [-pile for pile in piles] # Use negative values to simulate max-heap
heapq.heapify(max_heap)
for _ in range(k):
largest = -heapq.heappop(max_heap)
reduced = largest - largest // 2
heapq.heappush(max_heap, -reduced)
return -sum(max_heap)
# Example usage:
print(min_stone_sum([5, 4, 9], 2)) # Output: 12
print(min_stone_sum([4, 3, 6, 7], 3)) # Output: 12import java.util.PriorityQueue;
public class StoneRemoval {
public int minStoneSum(int[] piles, int k) {
PriorityQueue<Integer> maxHeap = new PriorityQueue<>( (a, b) -> b - a );
for (int pile : piles) {
maxHeap.add(pile);
}
for (int i = 0; i < k; i++) {
int largest = maxHeap.poll();
int reduced = largest - largest / 2;
maxHeap.add(reduced);
}
int totalStones = 0;
while (!maxHeap.isEmpty()) {
totalStones += maxHeap.poll();
}
return totalStones;
}
// Example usage
public static void main(String[] args) {
StoneRemoval sr = new StoneRemoval();
System.out.println(sr.minStoneSum(new int[]{5, 4, 9}, 2)); // Output: 12
System.out.println(sr.minStoneSum(new int[]{4, 3, 6, 7}, 3)); // Output: 12
}
}function minStoneSum(piles, k) {
const maxHeap = new MaxPriorityQueue();
piles.forEach(pile => maxHeap.enqueue(pile));
for (let i = 0; i < k; i++) {
let largest = maxHeap.dequeue().element;
let reduced = largest - Math.floor(largest / 2);
maxHeap.enqueue(reduced);
}
let totalStones = 0;
maxHeap.toArray().forEach(item => totalStones += item.element);
return totalStones;
}
// Example usage:
console.log(minStoneSum([5, 4, 9], 2)); // Output: 12
console.log(minStoneSum([4, 3, 6, 7], 3)); // Output: 12This Python solution uses the heapq library to maintain a max-heap (implemented as a min-heap with negative values). It performs k operations, each time reducing the largest pile. The final step returns the sum of the remaining piles.
Time Complexity: O(k log n) where n is the number of piles. Space Complexity: O(n) due to the heap storage.
Approach 2: Approach 2: Simulate Heap with Sorting
This approach involves using sorting to simulate the operations of a max-heap. The array of piles is repeatedly sorted to find the largest pile, then the operation is applied, and the sequence is repeated for k times.
#include <stdio.h>
#include <stdlib.h>
int compare(const void * a, const void * b) {
return (*(int*)b - *(int*)a);
}
int minStoneSum(int* piles, int pilesSize, int k) {
while (k--) {
qsort(piles, pilesSize, sizeof(int), compare);
piles[0] -= piles[0] / 2;
}
int total = 0;
for (int i = 0; i < pilesSize; i++) {
total += piles[i];
}
return total;
}
int main() {
int piles1[] = {5, 4, 9};
printf("%d\n", minStoneSum(piles1, 3, 2)); // Output: 12
int piles2[] = {4, 3, 6, 7};
printf("%d\n", minStoneSum(piles2, 4, 3)); // Output: 12
return 0;
}using System;
using System.Linq;
public class StoneRemoval {
public int MinStoneSum(int[] piles, int k) {
for (int i = 0; i < k; i++) {
Array.Sort(piles);
Array.Reverse(piles); // Max element at piles[0]
piles[0] -= piles[0] / 2;
}
return piles.Sum();
}
// Example usage
public static void Main() {
StoneRemoval sr = new StoneRemoval();
Console.WriteLine(sr.MinStoneSum(new int[]{5, 4, 9}, 2)); // Output: 12
Console.WriteLine(sr.MinStoneSum(new int[]{4, 3, 6, 7}, 3)); // Output: 12
}
}The C# solution applies sorting in each step to emulate the max-heap behavior. After sorting, it halves the effect of the largest element until k operations are achieved, finally calculating the sum of the remaining stones.
Time Complexity: O(k n log n), Space Complexity: O(1) (in-place manipulation).
Approach 3: Greedy + Priority Queue (Max Heap)
According to the problem description, in order to minimize the total number of remaining stones, we need to remove as many stones as possible from the stone piles. Therefore, we should always choose the pile with the most stones for removal.
We create a priority queue (max heap) pq to store the number of stones in each pile. Initially, we add the number of stones in all piles to the priority queue.
Next, we perform k operations. In each operation, we take out the top element x of the priority queue, halve x, and then add it back to the priority queue.
After performing k operations, the sum of all elements in the priority queue is the answer.
The time complexity is O(n + k times log n), and the space complexity is O(n). Where n is the length of the array piles.
class Solution {
public:
int minStoneSum(vector<int>& piles, int k) {
priority_queue<int> pq;
for (int x : piles) {
pq.push(x);
}
while (k--) {
int x = pq.top();
pq.pop();
pq.push(x - x / 2);
}
int ans = 0;
while (!pq.empty()) {
ans += pq.top();
pq.pop();
}
return ans;
}
};function minStoneSum(piles: number[], k: number): number {
const pq = new MaxPriorityQueue<number>();
for (const x of piles) {
pq.enqueue(x);
}
while (k--) {
pq.enqueue((pq.dequeue() + 1) >> 1);
}
return pq.toArray().reduce((a, b) => a + b, 0);
}func minStoneSum(piles []int, k int) (ans int) {
pq := &hp{piles}
heap.Init(pq)
for ; k > 0; k-- {
x := pq.pop()
pq.push(x - x/2)
}
for pq.Len() > 0 {
ans += pq.pop()
}
return
}
type hp struct{ sort.IntSlice }
func (h hp) Less(i, j int) bool { return h.IntSlice[i] > h.IntSlice[j] }
func (h *hp) Push(v any) { h.IntSlice = append(h.IntSlice, v.(int)) }
func (h *hp) Pop() any {
a := h.IntSlice
v := a[len(a)-1]
h.IntSlice = a[:len(a)-1]
return v
}
func (h *hp) push(v int) { heap.Push(h, v) }
func (h *hp) pop() int { return heap.Pop(h).(int) }Complexity comparison
| Approach | Complexity |
|---|---|
| Approach 1: Use a Max-Heap for Efficient Pile Reduction | Time Complexity: O(k log n) where n is the number of piles. Space Complexity: O(n) due to the heap storage. |
| Approach 2: Simulate Heap with Sorting | Time Complexity: O(k n log n), Space Complexity: O(1) (in-place manipulation). |
| Greedy + Priority Queue (Max Heap) | – |
Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Max-Heap (Priority Queue) | O(n + k log n) | O(n) | General case and interview settings where efficient repeated max selection is needed |
| Sorting Each Operation | O(k n log n) | O(1) | When heap libraries are unavailable or constraints are small |
Frequently asked questions
Is Remove Stones to Minimize the Total easy or hard?
The problem is classified as Medium difficulty. The main challenge is recognizing the greedy insight that the largest pile should always be reduced first and implementing it efficiently with a heap.
Remove Stones to Minimize the Total Python/Java solution
Python implementations typically use heapq with negative values to simulate a max-heap, while Java uses PriorityQueue with a reverse comparator. Both versions repeatedly pop the largest pile, reduce it by floor(pile/2), and push the updated pile back until k operations are completed.
What is the best approach for Remove Stones to Minimize the Total?
The most efficient approach uses a max-heap (priority queue). Always remove stones from the largest pile because it produces the biggest reduction in total stones. Extract the maximum pile, remove floor(pile/2), and push the updated value back into the heap. This greedy method runs in O(n + k log n) time with O(n) space.
How to solve Remove Stones to Minimize the Total in O(n + k log n)?
Insert all pile sizes into a max-heap. Repeat k times: remove the largest pile, compute floor(pile/2), subtract it from the pile, and push the updated value back into the heap. After all operations, sum the heap values to get the remaining stones. Each operation uses O(log n) heap operations.
Is Remove Stones to Minimize the Total asked at Google/Amazon/Meta?
This problem represents a common greedy + heap pattern frequently seen in interviews at companies like Amazon, Google, and Meta. Variants involving repeatedly selecting the largest element using a priority queue appear in many real interview questions.
What data structure is used in Remove Stones to Minimize the Total?
A max-heap (priority queue) is the key data structure. It allows efficient retrieval and update of the largest pile in O(log n) time. The problem combines heap operations with a greedy strategy to minimize the total stones.
What is the time complexity of Remove Stones to Minimize the Total?
The optimal heap-based solution runs in O(n + k log n) time. Building the max-heap takes O(n), and each of the k operations performs a heap extraction and insertion costing O(log n). Space complexity is O(n) for storing the heap.
