[链接描述]leetcode 题目。
有点类似于jump game, 只不过这里对步数有了隐形的要求,当前步数和之前步数有关。
如果我们用brute force的方法来解,每一步有三种可能,一共n个石头,时间复杂度就是O(3^n)。
这其中有很多步数是多余的,第i个石头无法从任何一个石头到达,那么我们应该立即中止搜寻。
还有一个石头可能由之前的多个石头到达,这又是可以优化的地方。
当前结果可由之前的结果得出,且有重复的搜索方法,就需要用DP。
public class Solution {
public boolean canCross(int[] stones) {
if(stones[1] != 1) return false;
int n = stones.length;
int[][] dp = new int[n][n]; // for ith stones, j means maximun previous steps
for(int i=0; i<n;i++){
for(int j=0; j<n;j++){
dp[i][j] = -1;
}
}
return canCross(dp, stones, 0, 0, n);
}
public boolean canCross(int[][] dp, int[] stones, int i, int j, int n){
if(dp[i][j] != -1) return dp[i][j] == 1;
if(i == n-1){
dp[i][j] = 1;
return true;
}
for(int k=i+1; k < n; k++){
if(stones[k] < stones[i] + j - 1){ // too close
continue;
} else if(stones[k] > stones[i] + j + 1){ // too far
dp[i][j] = 0;
continue;
} else { // j-1, j, j+1 three possibility
if(canCross(dp, stones, k, stones[k] - stones[i], n)){
dp[i][j] = 1;
return true;
}
}
}
dp[i][j] = 0;
return false;
}
}
public class Solution {
public boolean canCross(int[] stones) {
if(stones == null || stones.length == 0) return false;
int n = stones.length;
if(n == 1) return true;
if(stones[1] != 1) return false;
if(n == 2) return true;
HashSet<Integer> set = new HashSet<>();
for(int i = 0; i < n; i++){
if(i > 3 && stones[i] > stones[i-1]*2) return false;
set.add(stones[i]);
}
return canCross(set, stones[n-1], 1, 1);
}
public boolean canCross(HashSet<Integer> set, int last, int pos, int jump){
if(pos + jump == last || pos + jump + 1 == last || pos + jump -1 == last){
return true;
}
if(set.contains(pos + jump + 1)){
if(canCross(set, last, pos+jump+1, jump+1)) return true;
}
if(set.contains(pos + jump)){
if(canCross(set, last, pos+jump, jump)) return true;
}
if(jump > 1 && set.contains(pos + jump-1)){
if(canCross(set, last, pos+jump-1, jump-1)) return true;
}
return false;
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。