[LeetCode每日一题] 403. Frog Jump

207 阅读2分钟

两种解法。

第一种,第一直觉就是动态规划。令dp[i][step]表示跳了step格到达第i块石头是否可行,那么需要判断第stones[i]-step格是不是石头。这里我们转换一下,第一层循环是i,第二层是j,假设要从第j块石头跳到第i块石头,step为stones[i]-stones[i],现在要求dp[i][step],那么我们需要知道dp[j][step-1],dp[j][step]和dp[j][step+1]。还有一点需要注意,我们从第0块石头跳到第i块石头,最多跳了i次,由于每次从一块石头跳到另一块石头最多比前一次跳的step多一格,因此跳到第i块石头时最大的step为i,不得超过i。最终时间复杂度O(n2)O(n^2),空间复杂度O(n2)O(n^2).

var canCross = function(stones) {
    const n = stones.length
    if (stones[1] != 1) return false
    if (stones.length == 2) return true
    let dp = new Array(n).fill(null).map(d=>new Array(n).fill(false))
    dp[0][0] = true
    dp[1][1] = true
    for (let i = 2; i < n; i++) {
        for (let j = 0; j < i; j++) {
            let step = stones[i] - stones[j]
            if (step > i) continue
            dp[i][step] = dp[j][step] || dp[j][step-1] || dp[j][step+1]
            if (i==n-1&&dp[i][step]) return true
        }
    }
    return false
};

这里再介绍第二种解法。大多数人看到这题的直觉就是DFS,时间复杂度O(3n)O(3^n),即使加上剪枝在时间上也是严重超时。主要原因还是太多重复计算,我们采用记忆化搜索,参考自【宫水三叶】一题四解 : 降低确定「记忆化容器大小」的思维难度 & 利用「对偶性质」构造有效状态值 。时间复杂度O(n2)O(n^2),空间复杂度O(n2)O(n^2)

var canCross = function(stones) {
    const n = stones.length
    if (stones[1] != 1) return false
    if (n == 2) return true
    let visited = new Array(n).fill(null).map(d=>new Array(n).fill(false))
    let map = new Map()
    for (let i = 0; i < n; i++) map.set(stones[i], i)
    let deque = [[1,1]]
    visited[1][1] = true
    while (deque.length) {
        // 上一次是跳了step格到了第idx块石头,它所在的格子为stones[idx]
        const [idx, step] = deque.shift()
        if (idx == n-1) return true
        for (let x = -1; x <= 1; x++) {
            // 往前跳step+x格
            let next = stones[idx]+step+x
            if (next == stones[idx]) continue
            // 判断从第idx块石头即stones[idx]往前跳step+1格所在的格子是否是石头
            if (map.has(next)) {
                // 判断是否visited过
                let next_idx = map.get(next)
                if (!visited[next_idx][step+x]) {
                    visited[next_idx][step+x] = true
                    deque.push([next_idx,step+x])
                }
            }
        }
    }
    return false
};