算法 LC 跳躍游戲 II

題目描述

給你一個(gè)非負(fù)整數(shù)數(shù)組 nums ,你最初位于數(shù)組的第一個(gè)位置。

數(shù)組中的每個(gè)元素代表你在該位置可以跳躍的最大長(zhǎng)度。

你的目標(biāo)是使用最少的跳躍次數(shù)到達(dá)數(shù)組的最后一個(gè)位置。

假設(shè)你總是可以到達(dá)數(shù)組的最后一個(gè)位置。

示例 1:
輸入: nums = [2,3,1,1,4]
輸出: 2
解釋: 跳到最后一個(gè)位置的最小跳躍數(shù)是 2。
從下標(biāo)為 0 跳到下標(biāo)為 1 的位置,跳 1 步,然后跳 3 步到達(dá)數(shù)組的最后一個(gè)位置。

示例 2:
輸入: nums = [2,3,0,1,4]
輸出: 2

題解

思路1:正向遍歷
dp[i] 表示到達(dá)i點(diǎn)的最小布數(shù)
從0開始遍歷,計(jì)算由當(dāng)前點(diǎn)i所能到達(dá)的j點(diǎn)的dp[j] = min(dp[i]+1,dp[j]),dp[n-1] 即為結(jié)果

    static public func jump1(_ nums: [Int]) -> Int {
        let n = nums.count
        if n <= 1 {return 0}
        
        var dp = Array(repeating: Int.max/2, count: n)
        dp[0] = 0
        
        for i in 0..<n {
            var j = i+1
            let end = nums[i] + i
            
            while j <= end && j<n  {
                dp[j] = min(dp[i] + 1,dp[j])
                j += 1
            }
            
        }
        
        return dp[n-1]
        
    }

思路2:反向查找出發(fā)位置

由于總是可以到達(dá)數(shù)組的最后一個(gè)位置,因而數(shù)組中任意位置都可以到達(dá)

我們的目標(biāo)是到達(dá)數(shù)組的最后一個(gè)位置,因此我們可以考慮最后一步跳躍前所在的位置,該位置通過跳躍能夠到達(dá)最后一個(gè)位置。

如果有多個(gè)位置通過跳躍都能夠到達(dá)最后一個(gè)位置,我們可以「貪心」地選擇距離最后一個(gè)位置最遠(yuǎn)的那個(gè)位置,也就是對(duì)應(yīng)下標(biāo)最小的那個(gè)位置。因此,我們可以從左到右遍歷數(shù)組,選擇第一個(gè)滿足要求的位置。

找到最后一步跳躍前所在的位置之后,我們繼續(xù)貪心地尋找倒數(shù)第二步跳躍前所在的位置,以此類推,直到找到數(shù)組的開始位置

    static public func jump2(_ nums: [Int]) -> Int {
        let n = nums.count
        if n <= 1 {return 0}
        
        var steps = 0;
        var position = n-1

        while position>0 {
            for i in 0..<position {
                if nums[i] + i >= position {
                    position = i
                    steps += 1
                    break
                }
            }
        }
        
        return steps
        
    }

思路3:正向查找可到達(dá)的最大位置

如果我們「貪心」地進(jìn)行正向查找,每次找到可到達(dá)的最遠(yuǎn)位置,就可以在線性時(shí)間內(nèi)得到最少的跳躍次數(shù)

例如,對(duì)于數(shù)組 [2,3,1,2,4,2,3],初始位置是下標(biāo) 0,從下標(biāo) 0 出發(fā),最遠(yuǎn)可到達(dá)下標(biāo) 2。下標(biāo) 0 可到達(dá)的位置中,下標(biāo) 1 的值是 3,從下標(biāo) 1 出發(fā)可以達(dá)到更遠(yuǎn)的位置,因此第一步到達(dá)下標(biāo) 1。

從下標(biāo) 1 出發(fā),最遠(yuǎn)可到達(dá)下標(biāo) 4。下標(biāo) 1 可到達(dá)的位置中,下標(biāo) 4 的值是 4 ,從下標(biāo) 4 出發(fā)可以達(dá)到更遠(yuǎn)的位置,因此第二步到達(dá)下標(biāo) 4

    static public func jump3(_ nums: [Int]) -> Int {
        let n = nums.count
        if n <= 1 {return 0}
        
        var steps = 0;
        var maxPosition = 0
        var curLoc = 0
        
        for i in 0..<n {
            if nums[i] + i >= maxPosition {
                var j = i+1
                while j <= nums[i] + i  && j<n {
                    if nums[j] + j >= maxPosition || nums[j] + j >= n-1 {
                        maxPosition = nums[j] + j
                        curLoc = j
                    }
                    j += 1
                }
                steps += 1
                
                if curLoc == n-1 {
                    break
                }
            }
        
            
        }
        return steps
        
    }

優(yōu)化

我們維護(hù)當(dāng)前能夠到達(dá)的最大下標(biāo)位置,記為邊界。我們從左到右遍歷數(shù)組,到達(dá)邊界時(shí),更新邊界并將跳躍次數(shù)增加 1。

在遍歷數(shù)組時(shí),我們不訪問最后一個(gè)元素,這是因?yàn)樵谠L問最后一個(gè)元素之前,我們的邊界一定大于等于最后一個(gè)位置,否則就無法跳到最后一個(gè)位置了。如果訪問最后一個(gè)元素,在邊界正好為最后一個(gè)位置的情況下,我們會(huì)增加一次「不必要的跳躍次數(shù)」,因此我們不必訪問最后一個(gè)元素

    static public func jump4(_ nums: [Int]) -> Int {
        let n = nums.count
        if n <= 1 {return 0}
        
        var steps = 0;
        var maxPosition = 0
        var end = 0
        for i in 0..<(n-1) {
            maxPosition = max(maxPosition, nums[i]+i)
            if i == end {
                steps += 1
                end = maxPosition
            }
            
        }
        return steps
        
    }

參考:https://leetcode-cn.com/problems/jump-game-ii
https://leetcode-cn.com/problems/jump-game-ii/solution/tiao-yue-you-xi-ii-by-leetcode-solution/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容