LeetCode 403. Frog Jump

方法一:DFS+Memoization

dfs做最直接,但是会超时。

class Solution {
public:
    bool canCross(vector<int>& stones) {
        return dfs(stones,0,0);
    }
    
    bool dfs(vector<int> &stones, int start, int step){
        if (start==stones.size()-1) return true;
        
        for (int i=start+1;i<stones.size();++i){
            int gap=stones[i]-stones[start];
            if (gap>=step-1 && gap<=step+1){
                if (dfs(stones,i,gap)) return true;
            }
        }
        return false;
    }
};

 

DFS+Memoization

实际就是把所有return的地方就保存到memo再return,时间复杂度O(n^2)

class Solution {
public:
    bool canCross(vector<int>& stones) {
        int n=stones.size();
        vector<vector<int>> memo(n,vector<int>(n,-1));
        return dfs(stones,0,0,memo);
    }
    
    int dfs(vector<int> &stones, int start, int step, vector<vector<int>> &memo){
        if (memo[start][step]!=-1) return memo[start][step];
        
        if (start==stones.size()-1) 
            return memo[start][step]=1;
        
        for (int i=start+1;i<stones.size();++i){
            int gap=stones[i]-stones[start];
            if (gap>=step-1 && gap<=step+1){
                if (dfs(stones,i,gap,memo)==1) 
                    return memo[i][gap]=1;
            }
        }
        return memo[start][step]=0;
    }
};

 

方法二:DP

我最开始想的时候,dp[i][j] 表示用j跳到i,可不可行。dp[0][0]=true,

if dp[i][j]=true ->  dp[i+j-1][j-1]=dp[i+j][j]=dp[i+j+1][j+1]=true;

答案就是 dp[last index][j] for all j 其实是否有一个为true。

但是,由于题目中给的是 stones 的数组,数组元素并不连续,这么做空间复杂度太大。

但是可以改成 dp[i][j] 表示用j调到stones[i]可不可行,这样是可以做的,但是需要找下一个能到达石头的下标,并把 dp[新石头下标][j-1/j/j+1]=true

同样的思路,我们也可以用一个unordered_map<int,vector<int>>来记录 能跳到stones[i]的所有step,并和之前dp思路一样,更新后面能跳到的stone位置。

class Solution {
public:
    bool canCross(vector<int>& stones) {
        unordered_map<int,unordered_set<int>> m;
        for (auto stone:stones)
            m[stone] = unordered_set<int>();
        m[0].insert(0);
        
        for (auto stone:stones){
            for (int step:m[stone]){ // all steps that can reach stone
                for (int nextStep=step-1;nextStep<=step+1;++nextStep){
                    if (nextStep>0 && m.count(stone+nextStep)){
                        //cout << stone << ' ' << stone+nextStep << endl;
                        m[stone+nextStep].insert(nextStep);
                    }
                }
            }
        }
        return m[stones.back()].size() > 0;
    }
};

 

posted @ 2018-11-16 11:15  約束の空  阅读(223)  评论(0)    收藏  举报