python 贪心算法 动态规划实现 跳跃游戏ll【力扣题45】

news/2024/10/22 14:26:04/

作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。
会一些的技术:数据分析、算法、SQL、大数据相关、python
欢迎加入社区:码上找工作
作者专栏每日更新:
LeetCode解锁1000题: 打怪升级之旅
python数据分析可视化:企业实战案例
备注说明:方便大家阅读,统一使用python,带必要注释,公众号 数据分析螺丝钉 一起打怪升级

题目描述

LeetCode 题目 45:跳跃游戏 II

题目描述

给定一个非负整数数组 nums,你最初位于数组的第一个位置。数组中的每个元素代表你在该位置可以跳跃的最大长度(如果值是2则可以选择0、1、2进行跳跃 最大不超过2)。你的目标是使用最少的跳跃次数到达数组的最后一个位置。

输入格式
  • nums:一个非负整数数组。
输出格式
  • 返回到达数组最后一个位置的最小跳跃次数。

示例

示例 1
输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。从索引 0 跳到索引 1 的位置,跳1步,然后从索引 1 跳到索引 4,跳3步。
示例 2
输入: nums = [2,3,0,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。从索引 0 跳到索引 1 的位置,跳1步,然后从索引 1 跳到索引 4,跳3步。

功能和约束

  • 数组 nums 的长度不超过 10^4。
  • 每个元素的大小不超过 1000。
  • 你可以假设总是可以到达数组的最后一个位置。

这个问题要求找到一个高效的方法来确定达到数组末尾的最少跳跃次数。我们可以通过不同的策略来解决这个问题,包括动态规划、贪心算法等,来尽可能地减少计算时间和空间消耗。

方法一:贪心算法(正向)

解题步骤
  1. 初始化变量
    • end 表示当前能跳到的最远边界。
    • farthest 表示所有可选择跳的位置中,能跳到的最远位置。
    • jumps 记录跳跃次数。
  2. 遍历数组:除了最后一个元素,因为一旦到达最后一个元素,不需要再跳跃。
    • 更新能跳到的最远位置 farthest
    • 如果到达了当前的 end,即边界,更新边界并增加跳跃次数。
  3. 返回跳跃次数
完整代码
python">def jump(nums):"""使用贪心算法从前向后计算最少的跳跃次数:param nums: List[int], 每个位置可以跳跃的最大长度:return: int, 最少跳跃次数"""n = len(nums)end = farthest = jumps = 0for i in range(n - 1):  # 最后一个元素不需要访问farthest = max(farthest, i + nums[i])  # 更新能到达的最远位置if i == end:  # 到达上一跳能到的边界了jumps += 1  # 增加跳跃次数end = farthest  # 更新边界为当前能到达的最远位置if end >= n - 1:  # 如果已经能跳到最后位置breakreturn jumps# 示例调用
print(jump([2, 3, 1, 1, 4]))  # 输出: 2
算法分析
  • 时间复杂度:(O(N)),其中 (N) 是数组长度。
  • 空间复杂度:(O(1)),使用了有限的额外空间。

方法二:动态规划

解题步骤
  1. 初始化数组:创建一个数组 dp,其中 dp[i] 表示到达第 i 个位置的最少跳跃次数。
  2. 填充数组:初始化一个非常大的数表示无法到达的位置。
  3. 逐步更新:对于每个位置,尝试通过之前的所有位置跳到当前位置,更新 dp[i]
  4. 返回结果dp[n-1] 即为到达最后位置的最少跳跃次数。
完整代码
python">def jump(nums):"""使用动态规划计算到达最后位置的最少跳跃次数:param nums: List[int], 每个位置可以跳跃的最大长度:return: int, 最少跳跃次数"""n = len(nums)dp = [float('inf')] * ndp[0] = 0for i in range(1, n):for j in range(i):if j + nums[j] >= i:dp[i] = min(dp[i], dp[j] + 1)return dp[-1]# 示例调用
print(jump([2, 3, 1, 1, 4]))  # 输出: 2
算法分析
  • 时间复杂度:(O(N^2)),其中 (N) 是数组长度,每个元素需被重复访问和比较。
  • 空间复杂度:(O(N)),使用了一个与输入数组等长的 dp 数组。

方法三:贪心算法(反向)

解题步骤
  1. 初始化指针:从数组最后一个位置开始。
  2. 逆向查找:寻找最远可以一步跳到当前位置的起点。
  3. 更新位置:更新当前位置到找到的位置,增加跳跃次数。
  4. 重复执行:直到到达数组的开始位置。
完整代码
python">def jump(nums):"""使用贪心算法从后向前计算最少的跳跃次数:param nums: List[int], 每个位置可以跳跃的最大长度:return: int, 最少跳跃次数"""position = len(nums) - 1steps = 0while position > 0:for i in range(position):if i + nums[i] >= position:position = isteps += 1breakreturn steps# 示例调用
print(jump([2, 3, 1, 1, 4]))  # 输出: 2
算法分析
  • 时间复杂度:(O(N^2)),虽然是贪心算法,但在最坏情况下退化成平方级别的时间复杂度。
  • 空间复杂度:(O(1)),只使用了常数空间。

总结

下面的表格将展示它们在不同技术维度的性能和特点,包括时间复杂度、空间复杂度以及各自的优势和劣势。

特征方法一:正向贪心算法方法二:动态规划方法三:反向贪心算法
时间复杂度(O(N))(O(N^2))(O(N^2))
空间复杂度(O(1))(O(N))(O(1))
优势- 高效且直接
- 实现简单
- 理论上全面
- 易于理解和实现
- 无需预先知道全局信息
- 实现简单
劣势- 需要合理选择跳跃策略- 空间和时间消耗大
- 不适合大规模数据
- 时间复杂度高
- 可能多次迭代寻找最优点
适用场景- 大规模数据
- 需要最优时间性能
- 数据规模较小
- 对执行时间要求不高
- 理解问题的另一种方式
- 数据规模较小

综合分析

方法一(正向贪心算法

  • 这种方法通过从前往后贪心地选择每一跳的最远可达点,以最小化跳跃次数。其时间复杂度为线性,是解决此问题的最高效方法。适用于大规模数据,因为其空间复杂度极低。

方法二(动态规划)

  • 动态规划提供了一种全面检查所有可能性的方法,通过构建一个状态转移表来决定最少的跳跃次数。虽然这种方法在小规模数据上表现良好,但在大规模数据处理上由于其平方级时间复杂度表现不佳。

方法三(反向贪心算法

  • 反向贪心算法从数组的末端开始向前搜索,寻找能到达末端的最远起点,然后逐步逆向缩减问题规模。这种方法的优点是实现简单,但与正向贪心算法相比,其效率较低,因为它在最坏情况下的时间复杂度也是平方级。

在选择合适的算法时,应根据具体的应用需求和问题规模做出决策。对于大规模的实际应用,正向贪心算法通常是最优的选择,因为它提供了最好的时间和空间效率。对于教学或者问题规模较小的场合,可以考虑动态规划或反向贪心算法,以便更好地理解问题的结构。


http://www.ppmy.cn/news/1425763.html

相关文章

<个人笔记>基础算法模板题

1.基础算法 &#xff08;1&#xff09;一维前缀和 #include<iostream>using namespace std;const int N 1e510;int p[N],res[N]; int n,Q,l,r;int main() {cin >> n >> Q;for(int i 1;i<n;i){cin >> p[i];res[i] res[i - 1] p[i];}while(Q--)…

亚马逊云科技AWS免费3门网课+5门实验+证书重考券福利

亚马逊云科技AWS最新官方福利活动: AWSome Day&#xff0c;适用于正在备考AWS Practitioner认证&#xff0c;或者刚刚上手学习AWS的小伙伴们&#xff0c;不仅可以白嫖AWS官方精品在线课程&#xff0c;还能不花钱使用AWS服务做实验。 小李哥点评: 虽然福利不如以前的Awsome Day活…

C++修炼之路之继承<二>

目录 一&#xff1a;子类的六大默认成员函数 二&#xff1a;继承与友元 三&#xff1a;继承与静态成员 四&#xff1a;复杂的继承关系菱形继承菱形虚拟继承 1.单继承 2.多继承 3.菱形继承&#xff1b;一种特殊的多继承 4.菱形虚拟继承 5.虚拟继承解决数据冗余和二…

MySQL 8.0 vs MySQL 5.7: 详细比较

MySQL 8.0 vs MySQL 5.7: 详细比较 MySQL是世界上最流行的开源关系数据库之一&#xff0c;随着技术的进步&#xff0c;每个新版本都带来了许多重要的更新和改进。在本文中&#xff0c;我们将深入探讨MySQL 8.0和5.7两个版本之间的主要差异&#xff0c;涵盖从性能改进、新特性到…

如何用JAVA如何实现Word、Excel、PPT在线前端预览编辑的功能?

背景 随着信息化的发展&#xff0c;在线办公也日益成为了企业办公和个人学习不可或缺的一部分&#xff0c;作为微软Office的三大组成部分&#xff1a;Word、Excel和PPT也广泛应用于各种在线办公场景&#xff0c;但是由于浏览器限制及微软Office的不开源等特性&#xff0c;导致…

Spring Boot 中 Controller 接口参数注解全攻略与实战案例详解

引言 在 Spring Boot 应用程序中&#xff0c;Controller 是 MVC 架构模式中的核心组件之一&#xff0c;负责处理 HTTP 请求并返回响应结果。为了更好地映射请求、解析请求参数、执行业务逻辑和生成视图或 JSON 数据&#xff0c;Controller 中广泛使用了各种注解。本文将全面梳…

现代软件为什么要采用微服架构

现代软件采用微服务架构是为了解决传统单体架构在开发、部署和维护大型应用时面临的一系列问题。以下是采用微服务架构的主要优势&#xff1a; 1. **模块化和组件化**&#xff1a;微服务通过将应用拆分为一系列小型、松耦合的服务来提高模块化水平。每个服务都是围绕特定的业务…

【蓝桥杯 2020 国 B】美丽的 2 题解(Excel+提交答案)

问题描述 小蓝特别喜欢 2, 今年是公元 2020 年&#xff0c; 他特别高兴。他很好奇&#xff0c; 在公元 1 年到公元 2020 年&#xff08;包含&#xff09;中&#xff0c; 有多少个年份的数位中包含数字 2? 答案提交 这是一道结果填空的题&#xff0c; 你只需要算出结果后提交…