贪心
数组
动态规划
题目描述
给定一个长度为 n
的 0 索引 整数数组 nums
。初始位置为 nums[0]
。
每个元素 nums[i]
表示从索引 i
向前跳转的最大长度。换句话说,如果你在 nums[i]
处,你可以跳转到任意 nums[i + j]
处:
0 <= j <= nums[i]
i + j < n
返回到达 nums[n - 1]
的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]
。
示例 1:
输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
示例 2:
输入: nums = [2,3,0,1,4]
输出: 2
提示:
1 <= nums.length <= 104
0 <= nums[i] <= 1000
题目保证可以到达 nums[n-1]
解法
方法一:贪心
我们可以用变量 $mx$ 记录当前位置能够到达的最远位置,用变量 $last$ 记录上一次跳跃到的位置,用变量 $ans$ 记录跳跃的次数。
接下来,我们遍历 $[0,..n - 2]$ 的每一个位置 $i$,对于每一个位置 $i$,我们可以通过 $i + nums[i]$ 计算出当前位置能够到达的最远位置,我们用 $mx$ 来记录这个最远位置,即 $mx = max(mx, i + nums[i])$。接下来,判断当前位置是否到达了上一次跳跃的边界,即 $i = last$,如果到达了,那么我们就需要进行一次跳跃,将 $last$ 更新为 $mx$,并且将跳跃次数 $ans$ 增加 $1$。
最后,我们返回跳跃的次数 $ans$ 即可。
时间复杂度 $O(n)$,其中 $n$ 是数组的长度。空间复杂度 $O(1)$。
相似题目:
Python3 Java C++ Go TypeScript Rust C# C PHP
class Solution :
def jump ( self , nums : List [ int ]) -> int :
ans = mx = last = 0
for i , x in enumerate ( nums [: - 1 ]):
mx = max ( mx , i + x )
if last == i :
ans += 1
last = mx
return ans
1
2
3
4
5
6
7
8
9
10
11
12
13 class Solution {
public int jump ( int [] nums ) {
int ans = 0 , mx = 0 , last = 0 ;
for ( int i = 0 ; i < nums . length - 1 ; ++ i ) {
mx = Math . max ( mx , i + nums [ i ] );
if ( last == i ) {
++ ans ;
last = mx ;
}
}
return ans ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14 class Solution {
public :
int jump ( vector < int >& nums ) {
int ans = 0 , mx = 0 , last = 0 ;
for ( int i = 0 ; i < nums . size () - 1 ; ++ i ) {
mx = max ( mx , i + nums [ i ]);
if ( last == i ) {
++ ans ;
last = mx ;
}
}
return ans ;
}
};
func jump ( nums [] int ) ( ans int ) {
mx , last := 0 , 0
for i , x := range nums [: len ( nums ) - 1 ] {
mx = max ( mx , i + x )
if last == i {
ans ++
last = mx
}
}
return
}
function jump ( nums : number []) : number {
let [ ans , mx , last ] = [ 0 , 0 , 0 ];
for ( let i = 0 ; i < nums . length - 1 ; ++ i ) {
mx = Math . max ( mx , i + nums [ i ]);
if ( last === i ) {
++ ans ;
last = mx ;
}
}
return ans ;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 impl Solution {
pub fn jump ( nums : Vec < i32 > ) -> i32 {
let n = nums . len ();
let mut dp = vec! [ i32 :: MAX ; n ];
dp [ 0 ] = 0 ;
for i in 0 .. n - 1 {
for j in 1 ..= nums [ i ] as usize {
if i + j >= n {
break ;
}
dp [ i + j ] = dp [ i + j ]. min ( dp [ i ] + 1 );
}
}
dp [ n - 1 ]
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13 public class Solution {
public int Jump ( int [] nums ) {
int ans = 0 , mx = 0 , last = 0 ;
for ( int i = 0 ; i < nums . Length - 1 ; ++ i ) {
mx = Math . Max ( mx , i + nums [ i ]);
if ( last == i ) {
++ ans ;
last = mx ;
}
}
return ans ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #define min(a, b) a < b ? a : b
int jump ( int * nums , int numsSize ) {
int dp [ numsSize ];
for ( int i = 0 ; i < numsSize ; i ++ ) {
dp [ i ] = numsSize ;
}
dp [ 0 ] = 0 ;
for ( int i = 0 ; i < numsSize - 1 ; i ++ ) {
for ( int j = i + 1 ; j < ( min ( i + nums [ i ] + 1 , numsSize )); j ++ ) {
dp [ j ] = min ( dp [ j ], dp [ i ] + 1 );
}
}
return dp [ numsSize - 1 ];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 class Solution {
/**
* @param integer[] $nums
* @return integer
*/
function jump($nums) {
$maxReach = 0;
$steps = 0;
$lastJump = 0;
for ($i = 0; $i <= count($nums) - 2; $i++) {
$maxReach = max($maxReach, $i + $nums[$i]);
if ($i == $lastJump) {
$lastJump = $maxReach;
$steps++;
}
}
return $steps;
}
}