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; } };

浙公网安备 33010602011771号