首页 智能家居

动态规划精讲:最长递增子序列与摆动序列问题求解

分类:智能家居
字数: (6428)
阅读: (3095)
内容摘要:动态规划精讲:最长递增子序列与摆动序列问题求解,

在算法的世界里,动态规划:子序列问题 是一类非常经典且常见的题型。 其中,最长递增子序列 (Longest Increasing Subsequence, LIS) 和摆动序列 (Wiggle Subsequence) 是两个非常典型的例子。理解并掌握这两种问题的解法,对于提升动态规划的解题能力至关重要。本文将深入探讨这两种问题的底层原理,并提供可直接使用的代码示例。

最长递增子序列(LIS)

问题场景重现

给定一个无序的整数数组,找到其中最长递增子序列的长度。

例如,对于数组 [10, 9, 2, 5, 3, 7, 101, 18],最长递增子序列是 [2, 3, 7, 101],长度为 4。

底层原理深度剖析

解决 LIS 问题,动态规划是一种高效的方法。我们定义 dp[i] 表示以 nums[i] 结尾的最长递增子序列的长度。

动态规划精讲:最长递增子序列与摆动序列问题求解

状态转移方程如下:

dp[i] = max(dp[j] + 1) for all j < i and nums[j] < nums[i]

如果不存在任何 j 满足 nums[j] < nums[i],则 dp[i] = 1,表示以 nums[i] 结尾的最长递增子序列只有它自身。

动态规划精讲:最长递增子序列与摆动序列问题求解

最终的结果是 max(dp[i]) for all i

代码解决方案

def longest_increasing_subsequence(nums):
    n = len(nums)
    if n == 0:
        return 0
    
    dp = [1] * n  # 初始化 dp 数组,每个元素初始值为 1
    
    for i in range(1, n):
        for j in range(i):
            if nums[i] > nums[j]:
                dp[i] = max(dp[i], dp[j] + 1)
                
    return max(dp)  # 返回 dp 数组中的最大值

# 示例
nums = [10, 9, 2, 5, 3, 7, 101, 18]
print(longest_increasing_subsequence(nums)) # Output: 4

实战避坑经验总结

  1. 初始化dp 数组的初始化非常重要,确保每个位置的初始值正确,这里初始值为 1,表示至少包含自身。
  2. 边界条件:需要考虑数组为空的情况,避免空指针异常。
  3. 理解状态转移方程:深刻理解状态转移方程是解决动态规划问题的关键,确保能够正确地从子问题推导出当前问题的解。

摆动序列

问题场景重现

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列肯定是一个摆动序列。

给定一个整数序列,返回作为摆动序列的最长子序列的长度。

动态规划精讲:最长递增子序列与摆动序列问题求解

例如,对于数组 [1, 7, 4, 9, 2, 5],一个摆动序列是 [1, 7, 4, 9, 2],长度为 5。

底层原理深度剖析

解决摆动序列问题,我们需要维护两个 dp 数组:up[i]down[i]

up[i] 表示以 nums[i] 结尾的,且最后一个差值为正的摆动序列的长度。

动态规划精讲:最长递增子序列与摆动序列问题求解

down[i] 表示以 nums[i] 结尾的,且最后一个差值为负的摆动序列的长度。

状态转移方程如下:

  • 如果 nums[i] > nums[i-1],则 up[i] = down[i-1] + 1down[i] = down[i-1]
  • 如果 nums[i] < nums[i-1],则 down[i] = up[i-1] + 1up[i] = up[i-1]
  • 如果 nums[i] == nums[i-1],则 up[i] = up[i-1]down[i] = down[i-1]

最终的结果是 max(up[n-1], down[n-1])

代码解决方案

def wiggle_max_length(nums):
    n = len(nums)
    if n < 2:
        return n

    up = [1] * n
    down = [1] * n

    for i in range(1, n):
        if nums[i] > nums[i - 1]:
            up[i] = down[i - 1] + 1
            down[i] = down[i - 1]
        elif nums[i] < nums[i - 1]:
            down[i] = up[i - 1] + 1
            up[i] = up[i - 1]
        else:
            up[i] = up[i - 1]
            down[i] = down[i - 1]

    return max(up[n - 1], down[n - 1])

# 示例
nums = [1, 7, 4, 9, 2, 5]
print(wiggle_max_length(nums)) # Output: 5

实战避坑经验总结

  1. 理解 up 和 down 的含义:确保理解 updown 数组分别表示的含义,以及它们之间的关系。
  2. 处理相等的情况:当 nums[i] == nums[i-1] 时,up[i]down[i] 保持不变。
  3. 边界条件:对于长度小于 2 的数组,直接返回长度即可。

掌握了最长递增子序列和摆动序列的动态规划解法,可以让你在面对复杂的子序列问题时更加得心应手。希望本文能够帮助你更好地理解动态规划的思想,并在实际项目中灵活运用。在实际开发中,服务器性能监控可以使用 Prometheus + Grafana,通过反向代理 Nginx 将请求转发到不同的服务实例上实现负载均衡。同时,也可以使用宝塔面板来简化服务器管理和部署过程。优化服务器配置,例如调整 Nginx 的 worker 进程数和并发连接数,可以显著提升系统的吞吐量和响应速度。

动态规划精讲:最长递增子序列与摆动序列问题求解

转载请注明出处: 代码一只喵

本文的链接地址: http://m.acea1.store/article/14817.html

本文最后 发布于2026-04-12 21:40:16,已经过了15天没有更新,若内容或图片 失效,请留言反馈

()
您可能对以下文章感兴趣
评论
  • 接盘侠 3 天前
    学习了!动态规划确实是面试常考点,需要多加练习。
  • 夏天的风 3 天前
    点赞!代码注释很详细,可以直接拿来用,省了不少时间。
  • 拖延症晚期 4 天前
    写得真好!之前一直没搞懂摆动序列的动态规划解法,看了这篇文章思路清晰多了。
  • 单身狗 1 天前
    写得真好!之前一直没搞懂摆动序列的动态规划解法,看了这篇文章思路清晰多了。