4
4
</a >
5
5
<p align =" center " ><strong ><a href =" https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A " >参与本项目</a >,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong ></p >
6
6
7
+ > 相对于[ 贪心算法:跳跃游戏] ( https://mp.weixin.qq.com/s/606_N9j8ACKCODoCbV1lSA ) 难了不少,做好心里准备!
7
8
8
- > 相对于[ 贪心算法:跳跃游戏] ( https://mp.weixin.qq.com/s/606_N9j8ACKCODoCbV1lSA ) 难了不少,做好心里准备!
9
-
10
- # 45.跳跃游戏II
9
+ # 45.跳跃游戏 II
11
10
12
11
[ 力扣题目链接] ( https://leetcode.cn/problems/jump-game-ii/ )
13
12
18
17
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
19
18
20
19
示例:
21
- * 输入: [ 2,3,1,1,4]
22
- * 输出: 2
23
- * 解释: 跳到最后一个位置的最小跳跃数是 2。从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
20
+
21
+ - 输入: [ 2,3,1,1,4]
22
+ - 输出: 2
23
+ - 解释: 跳到最后一个位置的最小跳跃数是 2。从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
24
24
25
25
说明:
26
26
假设你总是可以到达数组的最后一个位置。
27
27
28
+ # 视频讲解
29
+
30
+ ** 《代码随想录》算法视频公开课:[ 贪心算法,最少跳几步还得看覆盖范围 | LeetCode: 45.跳跃游戏 II] ( https://www.bilibili.com/video/BV1Y24y1r7XZ ) ,相信结合视频在看本篇题解,更有助于大家对本题的理解** 。
28
31
29
32
## 思路
30
33
46
49
47
50
如图:
48
51
49
-
50
52
![ 45.跳跃游戏II] ( https://code-thinking-1253855093.file.myqcloud.com/pics/20201201232309103.png )
51
53
52
54
** 图中覆盖范围的意义在于,只要红色的区域,最多两步一定可以到!(不用管具体怎么跳,反正一定可以跳到)**
57
59
58
60
这里还是有个特殊情况需要考虑,当移动下标达到了当前覆盖的最远距离下标时
59
61
60
- * 如果当前覆盖最远距离下标不是是集合终点,步数就加一,还需要继续走。
61
- * 如果当前覆盖最远距离下标就是是集合终点,步数不用加一,因为不能再往后走了。
62
+ - 如果当前覆盖最远距离下标不是是集合终点,步数就加一,还需要继续走。
63
+ - 如果当前覆盖最远距离下标就是是集合终点,步数不用加一,因为不能再往后走了。
62
64
63
65
C++代码如下:(详细注释)
64
66
@@ -74,32 +76,34 @@ public:
74
76
for (int i = 0; i < nums.size(); i++) {
75
77
nextDistance = max(nums[ i] + i, nextDistance); // 更新下一步覆盖最远距离下标
76
78
if (i == curDistance) { // 遇到当前覆盖最远距离下标
77
- if (curDistance < nums.size() - 1) { // 如果当前覆盖最远距离下标不是终点
78
- ans++; // 需要走下一步
79
- curDistance = nextDistance; // 更新当前覆盖最远距离下标(相当于加油了)
80
- if (nextDistance >= nums.size() - 1) break; // 下一步的覆盖范围已经可以达到终点,结束循环
81
- } else break; // 当前覆盖最远距到达集合终点,不用做ans++操作了,直接结束
79
+ ans++; // 需要走下一步
80
+ curDistance = nextDistance; // 更新当前覆盖最远距离下标(相当于加油了)
81
+ if (nextDistance >= nums.size() - 1) break; // 当前覆盖最远距到达集合终点,不用做ans++操作了,直接结束
82
82
}
83
83
}
84
84
return ans;
85
85
}
86
86
};
87
87
```
88
88
89
+ * 时间复杂度: O(n)
90
+ * 空间复杂度: O(1)
91
+
92
+
89
93
## 方法二
90
94
91
95
依然是贪心,思路和方法一差不多,代码可以简洁一些。
92
96
93
97
**针对于方法一的特殊情况,可以统一处理**,即:移动下标只要遇到当前覆盖最远距离的下标,直接步数加一,不考虑是不是终点的情况。
94
98
95
- 想要达到这样的效果,只要让移动下标,最大只能移动到nums .size - 2的地方就可以了 。
99
+ 想要达到这样的效果,只要让移动下标,最大只能移动到 nums .size - 2 的地方就可以了 。
96
100
97
- 因为当移动下标指向nums .size - 2时 :
101
+ 因为当移动下标指向 nums .size - 2 时 :
98
102
99
- * 如果移动下标等于当前覆盖最大距离下标, 需要再走一步(即ans ++),因为最后一步一定是可以到的终点。(题目假设总是可以到达数组的最后一个位置),如图:
100
- 
103
+ - 如果移动下标等于当前覆盖最大距离下标, 需要再走一步(即 ans ++),因为最后一步一定是可以到的终点。(题目假设总是可以到达数组的最后一个位置),如图:
104
+ 
101
105
102
- * 如果移动下标不等于当前覆盖最大距离下标,说明当前覆盖最远距离就可以直接达到终点了,不需要再走一步。如图:
106
+ - 如果移动下标不等于当前覆盖最大距离下标,说明当前覆盖最远距离就可以直接达到终点了,不需要再走一步。如图:
103
107
104
108

105
109
@@ -125,9 +129,14 @@ public:
125
129
};
126
130
```
127
131
132
+ * 时间复杂度: O(n)
133
+ * 空间复杂度: O(1)
134
+
135
+
136
+
128
137
可以看出版本二的代码相对于版本一简化了不少!
129
138
130
- ** 其精髓在于控制移动下标i只移动到nums .size() - 2的位置 ** ,所以移动下标只要遇到当前覆盖最远距离的下标,直接步数加一,不用考虑别的了。
139
+ ** 其精髓在于控制移动下标 i 只移动到 nums .size() - 2 的位置 ** ,所以移动下标只要遇到当前覆盖最远距离的下标,直接步数加一,不用考虑别的了。
131
140
132
141
## 总结
133
142
@@ -137,11 +146,10 @@ public:
137
146
138
147
理解本题的关键在于:** 以最小的步数增加最大的覆盖范围,直到覆盖范围覆盖了终点** ,这个范围内最小步数一定可以跳到,不用管具体是怎么跳的,不纠结于一步究竟跳一个单位还是两个单位。
139
148
140
-
141
149
## 其他语言版本
142
150
151
+ ### Java
143
152
144
- ### Java
145
153
``` Java
146
154
// 版本一
147
155
class Solution {
@@ -207,7 +215,7 @@ class Solution:
207
215
nextDistance = 0
208
216
for i in range (len (nums)):
209
217
nextDistance = max (i + nums[i], nextDistance)
210
- if i == curDistance:
218
+ if i == curDistance:
211
219
if curDistance != len (nums) - 1 :
212
220
ans += 1
213
221
curDistance = nextDistance
@@ -230,9 +238,25 @@ class Solution:
230
238
step += 1
231
239
return step
232
240
```
241
+ ``` python
242
+ # 贪心版本三 - 类似‘55-跳跃游戏’写法
243
+ class Solution :
244
+ def jump (self , nums ) -> int :
245
+ if len (nums)== 1 : return 0
246
+ i = 0
247
+ count = 0
248
+ cover = 0
249
+ while i<= cover:
250
+ for i in range (i,cover+ 1 ):
251
+ cover = max (nums[i]+ i,cover)
252
+ if cover>= len (nums)- 1 : return count+ 1
253
+ count+= 1
254
+
255
+ ```
256
+
233
257
``` python
234
258
# 动态规划做法
235
- class Solution :
259
+ class Solution :
236
260
def jump (self , nums : List[int ]) -> int :
237
261
result = [10 ** 4 + 1 ]* len (nums)
238
262
result[0 ]= 0
@@ -244,7 +268,6 @@ class Solution:
244
268
245
269
```
246
270
247
-
248
271
### Go
249
272
250
273
``` go
@@ -331,21 +354,21 @@ var jump = function(nums) {
331
354
332
355
``` typescript
333
356
function jump(nums : number []): number {
334
- const length: number = nums .length ;
335
- let curFarthestIndex: number = 0 ,
336
- nextFarthestIndex: number = 0 ;
337
- let curIndex: number = 0 ;
338
- let stepNum: number = 0 ;
339
- while (curIndex < length - 1 ) {
340
- nextFarthestIndex = Math .max (nextFarthestIndex , curIndex + nums [curIndex ]);
341
- if (curIndex === curFarthestIndex ) {
342
- curFarthestIndex = nextFarthestIndex ;
343
- stepNum ++ ;
344
- }
345
- curIndex ++ ;
357
+ const length: number = nums .length ;
358
+ let curFarthestIndex: number = 0 ,
359
+ nextFarthestIndex: number = 0 ;
360
+ let curIndex: number = 0 ;
361
+ let stepNum: number = 0 ;
362
+ while (curIndex < length - 1 ) {
363
+ nextFarthestIndex = Math .max (nextFarthestIndex , curIndex + nums [curIndex ]);
364
+ if (curIndex === curFarthestIndex ) {
365
+ curFarthestIndex = nextFarthestIndex ;
366
+ stepNum ++ ;
346
367
}
347
- return stepNum ;
348
- };
368
+ curIndex ++ ;
369
+ }
370
+ return stepNum ;
371
+ }
349
372
```
350
373
351
374
### Scala
@@ -427,7 +450,6 @@ impl Solution {
427
450
}
428
451
```
429
452
430
-
431
453
<p align="center">
432
454
<a href="https://programmercarl.com/other/kstar.html " target="_ blank">
433
455
<img src =" ../pics/网站星球宣传海报.jpg " width =" 1000 " />
0 commit comments