面试经典150题 P55 跳跃游戏
时间轴
2025-10-02
init
题目:
我最先想到的是用队列遍历,BFS解法,用栈应该也行,可以看到这个复杂度相当大。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
using std::queue;
using std::unordered_set;
using std::vector;
class Solution {
public:
bool canJump(vector<int> &nums) {
int n = nums.size();
int jmp;
int curr;
int i, tmp;
queue<int> que;
unordered_set<int> uset;
if (n == 1) {
return true;
}
que.push(0);
uset.insert(0);
do {
curr = que.front();
jmp = nums[curr];
if (jmp == 0) {
que.pop();
uset.erase(curr);
continue;
}
for (i = 1; i <= jmp; i++) {
tmp = curr + i;
if (tmp == n - 1) {
return true;
} else if (tmp < n && uset.count(tmp) == 0) {
que.push(tmp);
uset.insert(tmp);
}
}
uset.erase(curr);
que.pop();
} while (!que.empty());
return false;
}
};
int main() {
Solution S;
vector<int> vec = {2, 5, 0, 0};
printf("%d\n", S.canJump(vec));
}
看了评论有一个解法很有趣,采用贪心策略,不用想具体过程,能跳多远就跳多远,如果跳过了最后的位置之后,那么必定能跳到最后位置。
1 | class Solution { |
这题也可以用动态规划,时间复杂度O(n^2)
dp[i] = true 表示能到达i, dp[i] = false 表示不能到达i
那么对于位置i,如果存在j( 0 <= j < i )能到达,并且j出发的最大跳跃距离能覆盖i,即:1
2
3
4
5if(j+nums[j]>=i){
dp[j] = true;
}else{
dp[j] = false;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using namespace std;
class Solution {
public:
bool canJump(vector<int>& nums) {
int n = nums.size();
vector<bool> dp(n, false);
dp[0] = true;
for (int i = 1; i < n; i++) {
for (int j = 0; j < i; j++) {
if (dp[j] && j + nums[j] >= i) {
dp[i] = true;
break; // 只要能到达,就不用再继续找
}
}
}
return dp[n-1];
}
};