当前位置:网站首页>[leetcode每日一题2021/4/29]403. 青蛙过河
[leetcode每日一题2021/4/29]403. 青蛙过河
2022-07-26 10:33:00 【LittleSeedling】
题目来源于leetcode,解法和思路仅代表个人观点。传送门。
难度:困难
时间:40min
TAG:动态规划
题目
一只青蛙想要过河。 假定河流被等分为若干个单元格,并且在每一个单元格内都有可能放有一块石子(也有可能没有)。 青蛙可以跳上石子,但是不可以跳入水中。
给你石子的位置列表 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 个石子之间的间距太大,没有可选的方案供青蛙跳跃过去。
提示:
2 <= stones.length <= 2000
0 <= stones[i] <= 231-1
stones[0] == 0
思路
先分析题目与示例,发现如下:
- 河流被等分为若干个单元格。如示例1中,河流就被分为18个单元格。示例2中,河流被分为12个单元格。
- 青蛙(除了第一步)每次能够跳跃的单位数 ==
(1)上次跳跃的单位数-1
(2)上次跳跃的单位数
(3)上次跳跃的单位数+1 - 青蛙并不是每个石子都要踩。
动态规划
不是官方动归解法,速度慢了许多。官方解法点我。
如果使用动态规划,我们需要初始化dp数组。
那么,
- dp数组的长度由什么确定?
- dp数组的维度有几维?
- 转移方程如何确定?
根据【提示】,
- stones数组长度<=2000==2*103。如果使用该变量作为dp数组的长度,算法时间复杂度可以使用O(n2)。
- stones[i]<=INT_MAX,如果使用该变量作为dp数组的长度,太大了,空间不够高。
leetcode的算力大概在O(n7~n8)左右。
那么,我们尝试着使用stones数组的长度作为dp数组的长度。
下面画图分析示例1:
【红色】表示每个石子之间的单位数。
【蓝色】表示石子位置。
【黄色】表示成功的跳跃路线。
【玫瑰色】表示失败的跳跃路径。
【橙色】表示到达当前石子的跳跃单位数。

6可以由3=>6,5=>6
8可以由6=>8,5=>8
对于每个状态dp[i],我们的状态从何转移过来?
肯定是由前面dp[0~i-1]之中转移过来的,那么我们遍历前面j=0~i-1的状态,【判断、是否能够转移到dp[i]。
判断条件:
- distance=stones[i] - stones[j]
- 到达状态dp[j]的跳跃单位数jump
- 是否满足jump-1==distance || jump == distance || jump+1 == distance
(这样时间复杂度是O(n2),经过上面的分析,leetcode应该可以接受)
我们需要保存,到达当前状态所跳跃的单位数,因为该变量可能有多个,所以我们对于每个状态dp[i]需要一个数组来记录。
所以,
- dp数组长度由stones长度确定
- dp数组维度为二维
- dp[i]由dp[0~i-1]转移
- 算法时间复杂度估计在O(n2)左右
代码
class Solution {
public:
bool canCross(vector<int>& stones) {
//石子数组长度
int n = stones.size();
/* 超时。 由于【到达dp[j]所跳跃的单位数】可能有多个,如果使用数组依次遍历,时间复杂度可能达到O(n³) */
// vector<vector<int>> dp(n);
// dp[0].push_back({0});
// for(int i=1;i<n;i++){
// for(int j=0;j<i;j++){
// //石子之间的距离
// int distance = stones[i] - stones[j];
// //对于j=[0,i-1],到达dp[j]所跳跃的单位数,判断是否满足条件
// for(auto rj:dp[j]){
// if(distance == rj-1 || distance == rj || distance == rj+1){
// dp[i].push_back(distance);
// }
// }
// }
// }
/* 使用set代替数组。 每次判断只需要3次,减少计算量。 为什么使用long? distance+1可能超出INT_MAX */
vector<unordered_set<long>> dp(n);
dp[0].insert(0);
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
//石子之间的距离
long distance = stones[i] - stones[j];
//对于每个石子的上一步 冲刺距离
if(dp[j].count(distance-1) || dp[j].count(distance) || dp[j].count(distance+1)){
dp[i].insert(distance);
}
}
}
return dp[n-1].size() != 0;
}
};
算法复杂度
时间复杂度: O(n2)。n为stones数组的长度。
空间复杂度: O(n2)。n为stones数组的长度。每个状态 需要记录 【到达当前状态】的所有跳跃数。

下面为官方解法的速度。对比起来,慢了许多。

边栏推荐
猜你喜欢
随机推荐
Google与Pixar开发Draco支持USD格式 加速3D对象传输&lt;转发&gt;
【杂谈】Error loading psycopg2 module :No module named psycopg2
.NET操作Redis String字符串
原生JS-获取transform值 x y z及rotate旋转角度
软件打不开了
我们的Web3创业项目,黄了
What is wrong about the description of function templates (how to solve link format errors)
Introduction to data analysis | kaggle Titanic mission (I) - > data loading and preliminary observation
[Halcon vision] morphological expansion
畅听,网文流量竞争的下一站?
Our Web3 entrepreneurship project is yellow
卸载魅族应用商店
.NET操作Redis Hash对象
并行、并发及对于高并发优化的几个方向
头歌 Phoenix 入门(第1关:Phoenix 安装、第2关:Phoenix 基础语法)
【Halcon视觉】图像灰度变化
利用原生js实现自定义滚动条(可点击到达,拖动到达)
数据库函数
微信公众号发布提醒(微信公众号模板消息接口)
Summary of common skills in H5 development of mobile terminal




![[Halcon vision] array](/img/29/905d93795a24538fded18d2d377e52.png)


![[Halcon vision] image filtering](/img/4b/e73a8d589b49276d96621f0ef02449.png)
