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

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

作者介绍: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 记录跳跃次数。
  1. 遍历数组:除了最后一个元素,因为一旦到达最后一个元素,不需要再跳跃。
  • 更新能跳到的最远位置 farthest
  • 如果到达了当前的 end,即边界,更新边界并增加跳跃次数。
  1. 返回跳跃次数
完整代码
def jump(nums):
    """
    使用贪心算法从前向后计算最少的跳跃次数
    :param nums: List[int], 每个位置可以跳跃的最大长度
    :return: int, 最少跳跃次数
    """
    n = len(nums)
    end = farthest = jumps = 0
    
    for i in range(n - 1):  # 最后一个元素不需要访问
        farthest = max(farthest, i + nums[i])  # 更新能到达的最远位置
        if i == end:  # 到达上一跳能到的边界了
            jumps += 1  # 增加跳跃次数
            end = farthest  # 更新边界为当前能到达的最远位置
            if end >= n - 1:  # 如果已经能跳到最后位置
                break
    
    return 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] 即为到达最后位置的最少跳跃次数。
完整代码
def jump(nums):
    """
    使用动态规划计算到达最后位置的最少跳跃次数
    :param nums: List[int], 每个位置可以跳跃的最大长度
    :return: int, 最少跳跃次数
    """
    n = len(nums)
    dp = [float('inf')] * n
    dp[0] = 0
    
    for 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. 重复执行:直到到达数组的开始位置。
完整代码
def jump(nums):
    """
    使用贪心算法从后向前计算最少的跳跃次数
    :param nums: List[int], 每个位置可以跳跃的最大长度
    :return: int, 最少跳跃次数
    """
    position = len(nums) - 1
    steps = 0
    
    while position > 0:
        for i in range(position):
            if i + nums[i] >= position:
                position = i
                steps += 1
                break
    
    return 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))
优势 - 高效且直接
- 实现简单
- 理论上全面
- 易于理解和实现
- 无需预先知道全局信息
- 实现简单
劣势 - 需要合理选择跳跃策略 - 空间和时间消耗大
- 不适合大规模数据
- 时间复杂度高
- 可能多次迭代寻找最优点
适用场景 - 大规模数据
- 需要最优时间性能
- 数据规模较小
- 对执行时间要求不高
- 理解问题的另一种方式
- 数据规模较小

综合分析

方法一(正向贪心算法)

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

方法二(动态规划)

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

方法三(反向贪心算法)

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

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


欢迎关注微信公众号 数据分析螺丝钉

相关文章
|
28天前
|
算法 Java C++
【潜意识Java】蓝桥杯算法有关的动态规划求解背包问题
本文介绍了经典的0/1背包问题及其动态规划解法。
47 5
|
3月前
|
算法 Python
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果;贪心算法在每一步选择局部最优解,追求全局最优;动态规划通过保存子问题的解,避免重复计算,确保全局最优。这三种算法各具特色,适用于不同类型的问题,合理选择能显著提升编程效率。
81 2
|
4月前
|
算法
动态规划算法学习三:0-1背包问题
这篇文章是关于0-1背包问题的动态规划算法详解,包括问题描述、解决步骤、最优子结构性质、状态表示和递推方程、算法设计与分析、计算最优值、算法实现以及对算法缺点的思考。
169 2
动态规划算法学习三:0-1背包问题
|
4月前
|
算法
动态规划算法学习四:最大上升子序列问题(LIS:Longest Increasing Subsequence)
这篇文章介绍了动态规划算法中解决最大上升子序列问题(LIS)的方法,包括问题的描述、动态规划的步骤、状态表示、递推方程、计算最优值以及优化方法,如非动态规划的二分法。
101 0
动态规划算法学习四:最大上升子序列问题(LIS:Longest Increasing Subsequence)
|
4月前
|
算法
动态规划算法学习二:最长公共子序列
这篇文章介绍了如何使用动态规划算法解决最长公共子序列(LCS)问题,包括问题描述、最优子结构性质、状态表示、状态递归方程、计算最优值的方法,以及具体的代码实现。
220 0
动态规划算法学习二:最长公共子序列
|
4月前
|
存储 算法
动态规划算法学习一:DP的重要知识点、矩阵连乘算法
这篇文章是关于动态规划算法中矩阵连乘问题的详解,包括问题描述、最优子结构、重叠子问题、递归方法、备忘录方法和动态规划算法设计的步骤。
250 0
|
4月前
Leetcode第55题(跳跃游戏)
LeetCode第55题“跳跃游戏”要求判断在一个非负整数数组中,从第一个位置出发,是否能够到达最后一个位置,其中每个位置的元素代表可跳跃的最大长度。
41 0
|
1天前
|
算法 数据安全/隐私保护 计算机视觉
基于FPGA的图像双线性插值算法verilog实现,包括tb测试文件和MATLAB辅助验证
本项目展示了256×256图像通过双线性插值放大至512×512的效果,无水印展示。使用Matlab 2022a和Vivado 2019.2开发,提供完整代码及详细中文注释、操作视频。核心程序实现图像缩放,并在Matlab中验证效果。双线性插值算法通过FPGA高效实现图像缩放,确保质量。
|
1月前
|
算法 数据安全/隐私保护 计算机视觉
基于Retinex算法的图像去雾matlab仿真
本项目展示了基于Retinex算法的图像去雾技术。完整程序运行效果无水印,使用Matlab2022a开发。核心代码包含详细中文注释和操作步骤视频。Retinex理论由Edwin Land提出,旨在分离图像的光照和反射分量,增强图像对比度、颜色和细节,尤其在雾天条件下表现优异,有效解决图像去雾问题。
|
1月前
|
算法 数据可视化 安全
基于DWA优化算法的机器人路径规划matlab仿真
本项目基于DWA优化算法实现机器人路径规划的MATLAB仿真,适用于动态环境下的自主导航。使用MATLAB2022A版本运行,展示路径规划和预测结果。核心代码通过散点图和轨迹图可视化路径点及预测路径。DWA算法通过定义速度空间、采样候选动作并评估其优劣(目标方向性、障碍物距离、速度一致性),实时调整机器人运动参数,确保安全避障并接近目标。
147 68

热门文章

最新文章