403. 青蛙过河
一只青蛙想要过河。 假定河流被等分为若干个单元格,并且在每一个单元格内都有可能放有一块石子(也有可能没有)。 青蛙可以跳上石子,但是不可以跳入水中。给你石子的位置列表 stones(用单元格序号 升序 表示), 请判定青蛙能否成功过河(即能否在最后一步跳至最后一块石子上)。
开始时, 青蛙默认已站在第一块石子上,并可以假定它第一步只能跳跃一个单位(即只能从单元格 1 跳至单元格 2 )。如果青蛙上一步跳跃了 k 个单位,那么它接下来的跳跃距离只能选择为 k - 1、k 或 k + 1 个单位。 另请注意,青蛙只能向前方(终点的方向)跳跃。
示例 1:
输入:stones = [0,1,3,5,6,8,12,17]
输出:true
解释:青蛙可以成功过河,按照如下方案跳跃:跳 1 个单位到第 2 块石子, 然后跳 2 个单位到第 3 块石子, 接着 跳 2 个单位到第 4 块石子, 然后跳 3 个单位到第 6 块石子, 跳 4 个单位到第 7 块石子, 最后,跳 5 个单位到第 8 个石子(即最后一块石子)。
示例 2:
输入:stones = [0,1,2,3,4,8,9,11]
输出:false
解释:这是因为第 5 和第 6 个石子之间的间距太大,没有可选的方案供青蛙跳跃过去。
方法一:BFS
从0号石子为起始原点,在栈中保存(石子,跳跃长度)
#include <iostream>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<map>
using namespace std;
class Solution {
public:
bool canCross(vector<int>& stones) {
int len=stones.size();
set<int> numset;
set<pair<int,int>> vistedset;
for(int i=0;i<stones.size();i++)
numset.insert(stones[i]);
queue<int> SQ,FQ;
SQ.push(stones[1]);FQ.push(stones[1]-stones[0]);
vistedset.insert(make_pair(stones[1],stones[1]-stones[0]));
while(!SQ.empty()){
int st=SQ.front(),foot=FQ.front();
SQ.pop();FQ.pop();
if(st==stones[len-1]) return true;
if(numset.find(st+foot)!=numset.end()&& vistedset.find(make_pair(st,foot))==vistedset.end()){
SQ.push(st+foot);FQ.push(foot);vistedset.insert(make_pair(st,foot));
}
if(numset.find(st+foot-1)!=numset.end() && vistedset.find(make_pair(st,foot-1))==vistedset.end()){
SQ.push(st+foot-1);FQ.push(foot-1);vistedset.insert(make_pair(st,foot-1));
}
if(numset.find(st+foot+1)!=numset.end()&& vistedset.find(make_pair(st,foot+1))==vistedset.end()){
SQ.push(st+foot+1);FQ.push(foot+1);vistedset.insert(make_pair(st,foot+1));
}
}
return false;
}
};
方法二:动态规划
DP[i]对应的数据结构为set,DP[i]记录到达第i石子的所有上一步的跳跃长度
#include <iostream>
#include<vector>
#include<set>
#include<map>
using namespace std;
class Solution {
public:
bool canCross(vector<int>& stones) {
int len = stones.size();
vector<set<int>> DP(len+10);
map<int,int> value2idx;
DP[1].insert(1);
for(int i=0;i<len;i++)
value2idx[stones[i]]=i;
for(int i=1;i<len;i++){
int s = stones[i];
for(int k:DP[i]){
for(int j=k-1;j<=k+1;j++){
int v = s+ j;
if(value2idx.find(v)!=value2idx.end()){
int idx = value2idx[v];
if(DP[idx].find(j)==DP[idx].end()){
DP[idx].insert(j);
}
}
}
}
}
return !DP[len-1].empty();
}
};