Leetcode 毎日の質問 - 45. ジャンプ ゲーム II (面接古典 150 の質問)

1. トピックの説明と要件

45. ジャンプゲーム II - LeetCode

トピックの説明

ゼロから始まる長さ n の整数配列 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]

2. 問題解決のアイデア

一般的なアイデア:

       まずトピックを分析しましょう。Jumping Game II は Jumping Game より少し複雑です。Jumping Game はジャンプによって最後の添字に到達できるかどうかを判断するだけで済みますが、Jumping Game II では最後の添字にジャンプするために必要な最小値を計算する必要があります。添え字. ジャンプの数。この点に関しては、貪欲なアルゴリズムのアイデアを引き続き使用できます。各添え字が到達できる最も遠い位置を見つけて、最も遠い位置が最後の添え字である添え字を見つけて、いつ実行するかを決定します。ジャンプすると同時にジャンプの回数を数えます。これが全体の概念です。全体的な概念から、2 つの問題を解決する必要があることがわかります。1 つは最後の添字に到達したかどうかを判断する方法、もう 1 つはジャンプの数をカウントする方法です。(各添え字に複数のジャンプ スキームがある可能性があるため)

      まず、最後の添え字に到達したか否かをどうやって判断するかというと、まずタイトルから「nums[n-1]まで到達することが保証されている」ということがわかるので、判断する必要はありませんが、最も遠い位置を取得するには、 nunsSize -1 として計算する必要がありますしたがって、for ループ メソッドを使用して配列全体を走査し、i+nums[i] の値 (現在の添え字が到達できる最も遠い位置) を計算し、それを現在の最も遠い位置と比較して、次の結果を得ることができます。比較大きな値。この継続的な計算により、site=numsSize-1 が得られます。これで最初の問題は解決します。[各範囲の最も遠い位置を見つけて、最後に最後の添字を見つけます]

       次に 2 番目の質問は、ジャンプの回数をどのように計算するかです。添字上にある場合、次の添字から到達できる最も遠い位置の添字であるジャンプ範囲を取得します。では、どのタイミングでジャンプするかを判断するのですが、1 歩の方が良い場合もあれば、2 歩の方が良い場合もあり、ジャンプの歩数は関係ありませんしたがって、いつ 1 回ジャンプする必要があるかを知る必要があるだけです。

       では、範囲内で自由にジャンプすることを選択できる場合、いつジャンプする必要があるのでしょうか? この範囲の境界に到達したときですか。この範囲の境界に到達したときは、この範囲の最も遠い位置を数えているため、間違いなくジャンプし、最後の添え字に到達するまで境界を更新し続けます最初の添え字から 1 ステップジャンプする必要があるため (どの添え字にジャンプしたかはわかりません)、初期境界は 0 に設定されます。その後、この境界をこれまでに取得した最も遠い添え字に更新して、続行します。この範囲内で到達できる最も遠い位置を見つけます [局所最適解]、どの添字にジャンプしたかを知る必要がないため、各範囲の境界を条件として使用してジャンプ数を計算します境界は、最小の回数が得られるように、最後の添字に到達して終了するまで回数を増やします。

       実際には、最後の添字まで範囲を拡張し続ける処理であり、この処理では、何度も境界に到達するということは、複数回ジャンプすることを意味します。

具体的な手順:

① 最小ジャンプ数 num、範囲境界端、最遠位置サイト変数を定義する

②最遠位置を更新するmax関数を定義する

③ 配列を走査して最遠位置を更新し、ジャンプ数を計算します。

④ジャンプ回数に戻る


3. 具体的なコード【C言語】

int max(int x,int y){
    return x>y?x:y;
}
int jump(int* nums, int numsSize){
    int num = 0;//达到nums[n-1]的最小跳跃次数
    int end = 0;//用来标志所能到达的最远边界
    int site=0;//能到达的最远位置
    for (int i = 0; i < numsSize-1; i++)
    {
        //通过遍历来找出每一个下标所能跳跃到的最远位置,取最远的
        site = max(site,i+nums[i]);
        //如果已经遍历到了所能到达的范围的边界,此时必须进行一次跳跃,同时更新所能到达的范围的边界
        if (i == end)
        {
            end = site;
            num++;
        }
    }
    return num;
}

おすすめ

転載: blog.csdn.net/m0_59800431/article/details/131615851