题目
思路
一个问题:利用青蛙能否到达第j
个石子(j<i
)的信息, 我们怎么判断青蛙是否能够到第i
个石子呢?
第i
个石子和第j
个石子之间的距离为gap = stones[i] - stones[j]
,因此,如果青蛙能够到达第j
个石子,并且到达第j
个石子时的跳跃长度为jump
,在jump + 1 == gap || jump == gap || jump - 1 == gap
时青蛙可以从第i
个石子到第j
个石子,而其他情况则不可以。为了判断能否到达第i
个石子,我们搜索j < i
的所有情况。
另外,根据每次跳跃的长度最多增加1的限制,青蛙跳跃到第j
个石子时跳跃长度jump
必定满足jump <= j(i从0开始)
。因此,其下一跳最大长度为j + 1
,因此在gap > j + 1
时必定无法完成跳跃。
根据上述分析,我们需要记录青蛙到达第j
个石子时所有可能的最后一跳的长度,这个长度将在判断后续石子能否到达时被查询使用 。为了提高查询效率,最后一跳的长度使用hash表来存放,这样我们就能快速判断该石子能否跳跃到后续间距为gap
的石子。(即gap
,gap+1
和gap - 1
是否位于垓石子的hash表中)。
我们使二维数组dp[i][k]
来保存到达第i
个石子时最后一跳的所有长度,数组的第一维表示不同的石子,第二维作为hash表保存当前石子的所有可能的最后一跳长度,即dp[i][k]==true
表示跳跃长度k
在hash表中,dp[i][k]==false
表示跳跃长度k
不在hash表中。
根据上述分析可知最长跳跃长度<= stone.size()-1
,因此hash
表最大长度为stones.size()
, 另外总共有stones.size()
个石子,因此二维数组dp
的长度为dp[stones.size()][stones.size()]
。
代码
class Solution {
public:
bool canCross(vector<int>& stones) {
int row_size = stones.size();
bool *dp = new bool[row_size * row_size];
for (int i=0; i<row_size * row_size; i++) {
dp[i] = false;
}
dp[0 * row_size + 0] = true;
for (int i=1; i<stones.size(); i++) {
int p = 0;
for(int j=i-1; j >= 0; j--) {
int gap = stones[i] - stones[j];
if (gap > (j + 1)) {
break;
}
dp[i * row_size + gap] = dp[j * row_size + gap - 1] || dp[j * row_size + gap] || dp[j * row_size + gap + 1];
}
}
for (int i=1; i < row_size; i++) {
if (dp[(row_size - 1) * row_size + i] == true) {
return true;
}
}
return false;
}
};