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
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,17 @@

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

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

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

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

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

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

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

<!-- tabs:start -->

Expand All @@ -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**
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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 }
Expand All @@ -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;
}
```

### **...**

```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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 }
Expand All @@ -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;
}
```

### **...**

```
Expand Down
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 }
Expand Down
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;
}
}
Loading