Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add solutions to lc problem: No.1962 #2144

Merged
merged 1 commit into from
Dec 23, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
feat: add solutions to lc problem: No.1962
No.1962.Remove Stones to Minimize the Total
yanglbme committed Dec 23, 2023
commit aad9386a912f5cfe35179895dadbf0f0abd6facd
Original file line number Diff line number Diff line change
@@ -57,7 +57,17 @@

<!-- 这里可写通用的实现逻辑 -->

**方法一:优先队列(大根堆)**
**方法一:贪心 + 优先队列(大根堆)**

根据题目描述,为了使得剩下的石子总数最小,我们需要尽可能多地移除石子堆中的石子。因此,每次应该选择数量最多的石子堆进行移除。

我们创建一个优先队列(大根堆) $pq$,用于存储石子堆的数量。初始时,将所有石子堆的数量加入优先队列。

接下来,我们进行 $k$ 次操作。在每一次操作中,我们取出优先队列的堆顶元素 $x$,将 $x$ 减半后重新加入优先队列。

在进行了 $k$ 次操作后,优先队列中所有元素的和即为答案。

时间复杂度 $O(n + k \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 是数组 `piles` 的长度。

<!-- tabs:start -->

@@ -68,13 +78,11 @@
```python
class Solution:
def minStoneSum(self, piles: List[int], k: int) -> int:
h = []
for p in piles:
heappush(h, -p)
pq = [-x for x in piles]
heapify(pq)
for _ in range(k):
p = -heappop(h)
heappush(h, -((p + 1) >> 1))
return -sum(h)
heapreplace(pq, pq[0] // 2)
return -sum(pq)
```

### **Java**
@@ -84,17 +92,17 @@ class Solution:
```java
class Solution {
public int minStoneSum(int[] piles, int k) {
PriorityQueue<Integer> q = new PriorityQueue<>((a, b) -> (b - a));
for (int p : piles) {
q.offer(p);
PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> b - a);
for (int x : piles) {
pq.offer(x);
}
while (k-- > 0) {
int p = q.poll();
q.offer((p + 1) >> 1);
int x = pq.poll();
pq.offer(x - x / 2);
}
int ans = 0;
while (!q.isEmpty()) {
ans += q.poll();
while (!pq.isEmpty()) {
ans += pq.poll();
}
return ans;
}
@@ -107,17 +115,19 @@ class Solution {
class Solution {
public:
int minStoneSum(vector<int>& piles, int k) {
priority_queue<int> q;
for (int& p : piles) q.push(p);
priority_queue<int> pq;
for (int x : piles) {
pq.push(x);
}
while (k--) {
int p = q.top();
q.pop();
q.push((p + 1) >> 1);
int x = pq.top();
pq.pop();
pq.push(x - x / 2);
}
int ans = 0;
while (!q.empty()) {
ans += q.top();
q.pop();
while (!pq.empty()) {
ans += pq.top();
pq.pop();
}
return ans;
}
@@ -127,19 +137,17 @@ public:
### **Go**
```go
func minStoneSum(piles []int, k int) int {
q := &hp{piles}
heap.Init(q)
for k > 0 {
p := q.pop()
q.push((p + 1) >> 1)
k--
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)
}
ans := 0
for q.Len() > 0 {
ans += q.pop()
for pq.Len() > 0 {
ans += pq.pop()
}
return ans
return
}
type hp struct{ sort.IntSlice }
@@ -156,6 +164,26 @@ func (h *hp) push(v int) { heap.Push(h, v) }
func (h *hp) pop() int { return heap.Pop(h).(int) }
```

### **TypeScript**

```ts
function minStoneSum(piles: number[], k: number): number {
const pq = new MaxPriorityQueue();
for (const x of piles) {
pq.enqueue(x);
}
while (k--) {
const x = pq.dequeue().element;
pq.enqueue(x - ((x / 2) | 0));
}
let ans = 0;
while (pq.size()) {
ans += pq.dequeue().element;
}
return ans;
}
```

### **...**

```
Original file line number Diff line number Diff line change
@@ -51,38 +51,48 @@ The total number of stones in [2,3,3,4] is 12.

## Solutions

**Solution 1: 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`.

<!-- tabs:start -->

### **Python3**

```python
class Solution:
def minStoneSum(self, piles: List[int], k: int) -> int:
h = []
for p in piles:
heappush(h, -p)
pq = [-x for x in piles]
heapify(pq)
for _ in range(k):
p = -heappop(h)
heappush(h, -((p + 1) >> 1))
return -sum(h)
heapreplace(pq, pq[0] // 2)
return -sum(pq)
```

### **Java**

```java
class Solution {
public int minStoneSum(int[] piles, int k) {
PriorityQueue<Integer> q = new PriorityQueue<>((a, b) -> (b - a));
for (int p : piles) {
q.offer(p);
PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> b - a);
for (int x : piles) {
pq.offer(x);
}
while (k-- > 0) {
int p = q.poll();
q.offer((p + 1) >> 1);
int x = pq.poll();
pq.offer(x - x / 2);
}
int ans = 0;
while (!q.isEmpty()) {
ans += q.poll();
while (!pq.isEmpty()) {
ans += pq.poll();
}
return ans;
}
@@ -95,17 +105,19 @@ class Solution {
class Solution {
public:
int minStoneSum(vector<int>& piles, int k) {
priority_queue<int> q;
for (int& p : piles) q.push(p);
priority_queue<int> pq;
for (int x : piles) {
pq.push(x);
}
while (k--) {
int p = q.top();
q.pop();
q.push((p + 1) >> 1);
int x = pq.top();
pq.pop();
pq.push(x - x / 2);
}
int ans = 0;
while (!q.empty()) {
ans += q.top();
q.pop();
while (!pq.empty()) {
ans += pq.top();
pq.pop();
}
return ans;
}
@@ -115,19 +127,17 @@ public:
### **Go**
```go
func minStoneSum(piles []int, k int) int {
q := &hp{piles}
heap.Init(q)
for k > 0 {
p := q.pop()
q.push((p + 1) >> 1)
k--
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)
}
ans := 0
for q.Len() > 0 {
ans += q.pop()
for pq.Len() > 0 {
ans += pq.pop()
}
return ans
return
}
type hp struct{ sort.IntSlice }
@@ -144,6 +154,26 @@ func (h *hp) push(v int) { heap.Push(h, v) }
func (h *hp) pop() int { return heap.Pop(h).(int) }
```

### **TypeScript**

```ts
function minStoneSum(piles: number[], k: number): number {
const pq = new MaxPriorityQueue();
for (const x of piles) {
pq.enqueue(x);
}
while (k--) {
const x = pq.dequeue().element;
pq.enqueue(x - ((x / 2) | 0));
}
let ans = 0;
while (pq.size()) {
ans += pq.dequeue().element;
}
return ans;
}
```

### **...**

```
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
class Solution {
public:
int minStoneSum(vector<int>& piles, int k) {
priority_queue<int> q;
for (int& p : piles) q.push(p);
while (k--) {
int p = q.top();
q.pop();
q.push((p + 1) >> 1);
}
int ans = 0;
while (!q.empty()) {
ans += q.top();
q.pop();
}
return ans;
}
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;
}
};
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
func minStoneSum(piles []int, k int) int {
q := &hp{piles}
heap.Init(q)
for k > 0 {
p := q.pop()
q.push((p + 1) >> 1)
k--
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)
}
ans := 0
for q.Len() > 0 {
ans += q.pop()
for pq.Len() > 0 {
ans += pq.pop()
}
return ans
return
}

type hp struct{ sort.IntSlice }
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
class Solution {
public int minStoneSum(int[] piles, int k) {
PriorityQueue<Integer> q = new PriorityQueue<>((a, b) -> (b - a));
for (int p : piles) {
q.offer(p);
}
while (k-- > 0) {
int p = q.poll();
q.offer((p + 1) >> 1);
}
int ans = 0;
while (!q.isEmpty()) {
ans += q.poll();
}
return ans;
}
class Solution {
public int minStoneSum(int[] piles, int k) {
PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> b - a);
for (int x : piles) {
pq.offer(x);
}
while (k-- > 0) {
int x = pq.poll();
pq.offer(x - x / 2);
}
int ans = 0;
while (!pq.isEmpty()) {
ans += pq.poll();
}
return ans;
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
class Solution:
def minStoneSum(self, piles: List[int], k: int) -> int:
h = []
for p in piles:
heappush(h, -p)
for _ in range(k):
p = -heappop(h)
heappush(h, -((p + 1) >> 1))
return -sum(h)
class Solution:
def minStoneSum(self, piles: List[int], k: int) -> int:
pq = [-x for x in piles]
heapify(pq)
for _ in range(k):
heapreplace(pq, pq[0] // 2)
return -sum(pq)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
function minStoneSum(piles: number[], k: number): number {
const pq = new MaxPriorityQueue();
for (const x of piles) {
pq.enqueue(x);
}
while (k--) {
const x = pq.dequeue().element;
pq.enqueue(x - ((x / 2) | 0));
}
let ans = 0;
while (pq.size()) {
ans += pq.dequeue().element;
}
return ans;
}