Skip to content

Commit 4d8a34c

Browse files
authored
feat: add solutions to lcp problem: No.30 (doocs#2294)
No.30.魔塔游戏
1 parent b45d0fe commit 4d8a34c

File tree

6 files changed

+244
-0
lines changed

6 files changed

+244
-0
lines changed

lcp/LCP 30. 魔塔游戏/README.md

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,143 @@
3131

3232
## 解法
3333

34+
### 方法一:贪心 + 优先队列(小根堆)
35+
36+
我们定义以下数据结构或变量,其中:
37+
38+
- 优先队列(小根堆) $q$:存储当前所有怪物房间的血量减少值,堆顶元素为血量减少值最大的怪物房间(也即是最小的负数)。
39+
- 血量 $blood$:存储当前的血量,初始时 $blood = 1$。
40+
- 操作次数 $ans$:存储已经进行的操作次数,初始时 $ans = 0$。
41+
- 临时变量 $v$:存储当前待减少的血量,初始时 $v = 0$。
42+
43+
我们按照房间编号升序遍历所有房间,对于当前遍历到的房间 $x$,如果 $x$ 为怪物房间,我们就将 $x$ 的血量减少值加入 $q$。然后,我们更新当前的血量 $blood$,即 $blood = blood + x$。如果此时 $blood \le 0$,说明当前的血量不足以通过当前房间,因此我们需要调整访问顺序,此时我们可以贪心地将 $q$ 中血量减少值最大的房间调整至访问顺序的末尾,即把它累加到临时变量 $v$ 上,然后将 $blood$ 增加对应的值,并将该房间从 $q$ 中弹出。
44+
45+
遍历结束后,我们需要更新当前的血量 $blood$,即 $blood = blood + v$。如果此时 $blood \le 0$,说明无法访问完所有房间,返回 $-1$。否则,返回 $ans$。
46+
47+
时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$,其中 $n$ 为房间的数量。
48+
49+
<!-- tabs:start -->
50+
51+
```python
52+
class Solution:
53+
def magicTower(self, nums: List[int]) -> int:
54+
q = []
55+
blood = 1
56+
ans = v = 0
57+
for x in nums:
58+
if x < 0:
59+
heappush(q, x)
60+
blood += x
61+
if blood <= 0:
62+
ans += 1
63+
v += q[0]
64+
blood -= heappop(q)
65+
blood += v
66+
return -1 if blood <= 0 else ans
67+
```
68+
69+
```java
70+
class Solution {
71+
public int magicTower(int[] nums) {
72+
PriorityQueue<Integer> q = new PriorityQueue<>();
73+
long blood = 1, v = 0;
74+
int ans = 0;
75+
for (int x : nums) {
76+
if (x < 0) {
77+
q.offer(x);
78+
}
79+
blood += x;
80+
if (blood <= 0) {
81+
++ans;
82+
v += q.peek();
83+
blood -= q.poll();
84+
}
85+
}
86+
blood += v;
87+
return blood <= 0 ? -1 : ans;
88+
}
89+
}
90+
```
91+
92+
```cpp
93+
class Solution {
94+
public:
95+
int magicTower(vector<int>& nums) {
96+
priority_queue<int, vector<int>, greater<int>> q;
97+
int64_t blood = 1, v = 0;
98+
int ans = 0;
99+
for (int x : nums) {
100+
if (x < 0) {
101+
q.push(x);
102+
}
103+
blood += x;
104+
if (blood <= 0) {
105+
++ans;
106+
v += q.top();
107+
blood -= q.top();
108+
q.pop();
109+
}
110+
}
111+
blood += v;
112+
return blood <= 0 ? -1 : ans;
113+
}
114+
};
115+
```
116+
117+
```go
118+
func magicTower(nums []int) (ans int) {
119+
q := hp{}
120+
blood, v := 1, 0
121+
for _, x := range nums {
122+
if x < 0 {
123+
heap.Push(&q, x)
124+
}
125+
blood += x
126+
if blood <= 0 {
127+
ans++
128+
t := heap.Pop(&q).(int)
129+
v += t
130+
blood -= t
131+
}
132+
}
133+
if blood+v <= 0 {
134+
return -1
135+
}
136+
return ans
137+
}
138+
139+
type hp struct{ sort.IntSlice }
140+
141+
func (h hp) Less(i, j int) bool { return h.IntSlice[i] < h.IntSlice[j] }
142+
func (h *hp) Push(v any) { h.IntSlice = append(h.IntSlice, v.(int)) }
143+
func (h *hp) Pop() any {
144+
a := h.IntSlice
145+
v := a[len(a)-1]
146+
h.IntSlice = a[:len(a)-1]
147+
return v
148+
}
149+
```
150+
151+
```ts
152+
function magicTower(nums: number[]): number {
153+
const q = new MinPriorityQueue();
154+
let [ans, blood, v] = [0, 1, 0];
155+
for (const x of nums) {
156+
if (x < 0) {
157+
q.enqueue(x);
158+
}
159+
blood += x;
160+
if (blood <= 0) {
161+
++ans;
162+
const t = q.dequeue().element;
163+
blood -= t;
164+
v += t;
165+
}
166+
}
167+
return blood + v <= 0 ? -1 : ans;
168+
}
169+
```
170+
171+
<!-- tabs:end -->
172+
34173
<!-- end -->

lcp/LCP 30. 魔塔游戏/Solution.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
class Solution {
2+
public:
3+
int magicTower(vector<int>& nums) {
4+
priority_queue<int, vector<int>, greater<int>> q;
5+
int64_t blood = 1, v = 0;
6+
int ans = 0;
7+
for (int x : nums) {
8+
if (x < 0) {
9+
q.push(x);
10+
}
11+
blood += x;
12+
if (blood <= 0) {
13+
++ans;
14+
v += q.top();
15+
blood -= q.top();
16+
q.pop();
17+
}
18+
}
19+
blood += v;
20+
return blood <= 0 ? -1 : ans;
21+
}
22+
};

lcp/LCP 30. 魔塔游戏/Solution.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
func magicTower(nums []int) (ans int) {
2+
q := hp{}
3+
blood, v := 1, 0
4+
for _, x := range nums {
5+
if x < 0 {
6+
heap.Push(&q, x)
7+
}
8+
blood += x
9+
if blood <= 0 {
10+
ans++
11+
t := heap.Pop(&q).(int)
12+
v += t
13+
blood -= t
14+
}
15+
}
16+
if blood+v <= 0 {
17+
return -1
18+
}
19+
return ans
20+
}
21+
22+
type hp struct{ sort.IntSlice }
23+
24+
func (h hp) Less(i, j int) bool { return h.IntSlice[i] < h.IntSlice[j] }
25+
func (h *hp) Push(v any) { h.IntSlice = append(h.IntSlice, v.(int)) }
26+
func (h *hp) Pop() any {
27+
a := h.IntSlice
28+
v := a[len(a)-1]
29+
h.IntSlice = a[:len(a)-1]
30+
return v
31+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class Solution {
2+
public int magicTower(int[] nums) {
3+
PriorityQueue<Integer> q = new PriorityQueue<>();
4+
long blood = 1, v = 0;
5+
int ans = 0;
6+
for (int x : nums) {
7+
if (x < 0) {
8+
q.offer(x);
9+
}
10+
blood += x;
11+
if (blood <= 0) {
12+
++ans;
13+
v += q.peek();
14+
blood -= q.poll();
15+
}
16+
}
17+
blood += v;
18+
return blood <= 0 ? -1 : ans;
19+
}
20+
}

lcp/LCP 30. 魔塔游戏/Solution.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class Solution:
2+
def magicTower(self, nums: List[int]) -> int:
3+
q = []
4+
blood = 1
5+
ans = v = 0
6+
for x in nums:
7+
if x < 0:
8+
heappush(q, x)
9+
blood += x
10+
if blood <= 0:
11+
ans += 1
12+
v += q[0]
13+
blood -= heappop(q)
14+
blood += v
15+
return -1 if blood <= 0 else ans

lcp/LCP 30. 魔塔游戏/Solution.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
function magicTower(nums: number[]): number {
2+
const q = new MinPriorityQueue();
3+
let [ans, blood, v] = [0, 1, 0];
4+
for (const x of nums) {
5+
if (x < 0) {
6+
q.enqueue(x);
7+
}
8+
blood += x;
9+
if (blood <= 0) {
10+
++ans;
11+
const t = q.dequeue().element;
12+
blood -= t;
13+
v += t;
14+
}
15+
}
16+
return blood + v <= 0 ? -1 : ans;
17+
}

0 commit comments

Comments
 (0)