LeetCode 403.青蛙过河

LeetCode 403.青蛙过河

      • 题目
      • 解题思路
      • 代码

题目

LeetCode 403.青蛙过河_第1张图片

解题思路

LeetCode 403.青蛙过河_第2张图片

这道题第一眼看上去就能想到要用递归,因此可以先写出递归的实现代码,但别提交因为递归的时间复杂度很高,此题又是困难题,因此暴力递归肯定时间超时。所以为了保证我们的通过率,还应再次基础上进行记忆化搜索来优化算法。
递归第一步先考虑怎么出来,此题结束递归的条件为判断当前位置经过{k-1,k,k+1}步能不能刚好到达最后一颗石子,即stones[i] + (k-1 || k || k+1) == stones[stones.lenth - 1];
第二步考虑怎么进行递归,当我们通过k步来到第stones[i]块石头的位置,考虑能否经过{k-1,k,k+1}步刚好到达有石头的地方,如果有再继续遍历。

之后优化。
首先我们需要知道我们要保存的东西是什么。应该是当我来到第i块石头要向前走m步的时候我想知道先前的递归是不是已经有过这样子的先例如果有,那么直接根据之前的结果返回上一层,不需要继续往下递归,从而节省时间。

比起动态规划,递归+记忆化搜索是一种比较好想到的算法,唯一的缺点就是代码量可能比较长.

代码

//递归+记忆化搜索(Myself)
class Solution {
    int[][] dp;
    public boolean canCross(int[] stones) {
        dp = new int[stones.length][stones.length];
        return path(stones, 1, 0);
    }
    public boolean path(int[] stones, int k, int count) {
        int n = stones.length;
        boolean flag = false;
        if(dp[count][k] > 0) {
            return true;
        }else if(dp[count][k] < 0) {
            return false;
        }
        if(stones[count] + k == stones[n - 1]) {
            return true;
        }
        if((stones[count] + k) >= stones[count + 1]) {
            for (int i = count + 1; i < n; i++){
                if((stones[count] + k) == stones[i]) {
                    flag = path(stones, k-1, i);
                    dp[i][k-1] = flag == false ? -1 : 1;
                    if (flag){
                        break;
                    }
                    flag = path(stones, k, i);
                    dp[i][k] = flag == false ? -1 : 1;
                    if (flag){
                        break;
                    }
                    flag = path(stones, k+1, i);
                    dp[i][k+1] = flag == false ? -1 : 1;
                    break;
                }
            } 
        }  
        return flag;
    }
}

你可能感兴趣的:(算法,leetcode,算法,java)