タイトル説明
https://leetcode-cn.com/problems/jump-game-ii/
解決
最初に頭に浮かぶのは、動的計画法を実行することです。
- インデックスiにジャンプするために必要な最小ステップ数を表すdp [i]配列を維持します
- 次に、再帰的にdp [i + 1]を実行する場合、前のi dp [i]の座標i + 1にジャンプできる最小のステップ数の合計を見つけるだけで済みます。
- dp [nums.length]
コードを返します。
class Solution {
public int jump(int[] nums) {
//状态:当前的位置i,要到达的位置j,使用的跳跃次数
if(nums==null || nums.length==0||nums.length==1 ) return 0;
int []dp = new int[nums.length];//表示从0到达下标i所需要的最少跳跃数
dp[1] = 1;
for(int i=1;i<nums.length;i++){
int step = nums.length;//默认为最大值
for(int j=0;j<i;j++){
//遍历之前的dp[j],找到一个最少的步数,取之为dp[i];
if(nums[j]>=i-j){
//从下标j能达到下标i
int temp = dp[j]+ 1;//跳跃数加1
if(step>temp){
step = temp;
}//计算从0走到i,需要的最少步数
}
}
dp[i] = step;//更新从0到i要走的最少步数
}
return dp[nums.length-1];
}
}
コードは多くのテストケースに合格できますが、タイムアウトになります。
要素の数は約25,000であり、O(n 2)の複雑さを乗り切ることができないことを示しています。動的計画法がタイムアウトしたため、問題が貪欲であることを示しています。
欲張りアルゴリズムを使用して、この質問の欲張りな選択について考える必要があります。
- 最も遠い距離に到達するために毎回ジャンプする最大ステップ数を選択します(反例を与えることができます)
- 最も近い距離に到達するために毎回ジャンプする最小のステップ数を選択します(明らかにそうではありません)
- ジャンプできるすべての位置にジャンプすることを選択するたびに、最も遠い位置に到達できる位置。たとえば
、下付き文字0にある場合、nums [0]は3です。つまり、3つの位置にジャンプできます1 、2、3、およびnums [2] = 3、最も遠い5、nums [1] = 2、最も遠い3、nums [3] = 1、最も遠い1、次にジャンプすることを選択します下付き文字2の位置に移動します。これは、この時点で到達できる位置が最も遠いためです。つまり、範囲内の位置に到達するために必要なジャンプの数は1回だけです。
ただし、この時点で3が終了している場合は、直接3にジャンプします。したがって、添え字の処理に少し注意を払う必要があります。
次の写真は、公式の問題解決策からのものです:https://leetcode-cn.com/problems/jump-game-ii/solution/tiao-yue-you-xi-ii-by-leetcode-solution/
したがって、次のコードを取得できます。
class Solution {
public int jump(int[] nums) {
if(nums==null || nums.length==0||nums.length==1 ) return 0;
int end = 0;//记录当前能跳到的位置的边界
int jumps = 0,farthest=0;//跳跃次数
for(int i=0;i<nums.length-1;i++){
//i不一定表示当前位置,但是属于当前位置的边界之内
//如果end边界=nums.length,不需要step++,所以这里只需要<nums.length-1
//获取最大的跳远范围
farthest = Math.max(nums[i]+i,farthest);
if(end==i){
//到达了边界,开始下一次跳跃,step++
jumps++;//跳跃数++
end = farthest;//更新现在的边界,
}
}
return jumps;
}
}