class Solution {
/*
Date: 07/14/2020
Strategy: Dynamic programming
Use a 2D boolean array to store the possible jump units at every stone. The rows represent the stones and the column represents the jump units possible at each stone.
For current stone we check if it can be reached from every previous stone. If yes, then we set the (jump-1), (jump), (jump+1) columns to true for the current stone. Repeat this for all the stones.
When we reach the last stone, if it can be reached from any of the previous stone, we reached the end successfully. Return true. Otherwise, false.
Runtime: 24 ms, faster than 75.45% of Java online submissions for Frog Jump.
Memory Usage: 43.5 MB, less than 63.29% of Java online submissions for Frog Jump.
Time complexity: O(N^2)
Space complexity: O(N^2)
*/
public boolean canCross(int[] stones) {
int len = stones.length;
if (len <= 1) {
return true;
}
int N = stones.length;
// The rows represent the stones and the columns represent the jumps that can be taken at this stone
boolean[][] dp = new boolean[N][N];
// Because we take 1 jump at first stone
dp[0][1] = true;
// For each stone, we check if we can reach to it from any of the previous stones
for (int i=1; i<N; i++) { // i represents the current stone
for (int j=0; j<i; j++) { // j represent the previous stones
int dist = stones[i] - stones[j];
// if distance is out of boundary or if we cannot reach the current stone from the previous stone
if (dist < 0 || dist > N-1 || !dp[j][dist]) {
continue;
}
if (dp[j][dist]) { // we can reach the current stone i from the stone j at a distance dist. If the current stone is the last stone, then we reached the end. Return true.
if (i == N-1) {
return true;
}
dp[i][dist-1] = dp[i][dist] = dp[i][dist+1] = true; // set the possible jumps that can be taken at current stone to true
}
}
}
return false;