memo[i][j] = 1 means that the frog can reach the final destination from i-th stone, with j being the previous step size. Because the maximum previous step size for the 0th, 1th, 2th stone is 0, 1, 2, ... , which means the maximum j is equal to i. So we can declare the matrix size as n*n where n is the number of stones.

If ignoring the recursive call overhead, this algorithm should have a time complexity of O(n^2) because we are just filling half of this matrix memo.

```
public class Solution {
public boolean canCross(int[] stones) {
if(stones[1] != 1) return false;
int n = stones.length;
int[][] memo = new int[n][n];
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++)
{
memo[i][j] = -1;
}
}
return canCross(stones, 0, 0, memo, n);
}
private boolean canCross(int[] stones, int i, int j, int[][] memo, int n) {
if(memo[i][j]!=-1) return memo[i][j] == 1;
if(i == n - 1) {
memo[i][j] = 1;
return true;
}
for(int k = i + 1; k < n; k++) {
if(stones[k] < j - 1 + stones[i]) continue;
else if(stones[k] > j + 1 + stones[i]) {
memo[i][j] = 0;
return false;
}
else {
if(canCross(stones, k, stones[k] - stones[i], memo, n)) {
memo[i][j] = 1;
return true;
}
}
}
memo[i][j] = 0;
return false;
}
}
```