LeetCode | 动态规划算法(DP)求解最大最长系列问题(python版,最全解析)

本文介绍了使用动态规划方法解决LeetCode中的最长递增子序列、最长公共子序列和最长回文子序列问题,并提供了Python解法。通过dp数组定义、初始化和递推公式详细解析每个问题,帮助理解动态规划思想。
摘要由CSDN通过智能技术生成

动态规划解法由于不用考虑中间结果的暂存,不用输出所有可能情况的集合,只需要求解问题的个数。所以dp很适合求解最大、最长系列问题。

最长递增子序列(LIS)

  • leetcode300 LongestIncreaseSubsequence

Given an unsorted array of integers, find the length of longest increasing subsequence.
For example, given [10, 9, 2, 5, 3, 7, 101, 18], the longest increasing subsequence is [2, 3, 7, 101].
Therefore the length is 4.

求解:

def find_LIS(nums):
    """
    type:nums:list
    rtype: int
    """
    n = len(nums)

    # 1. dp 定义
    # dp[i] 为nums[i]对应能得到的最长递增子序列

    # 2. dp 初始化
    dp = [1 for i in range(n)]

    res = 0
    # 3. dp 递推
    for i in range(1, n):
        for j in range(i):
            if nums[i] > nums[j] and dp[i] < dp[j] + 1:
                #当前数比nums[j],可构成的最大递增子序列长度对j而言为dp[j]加1,这里我们要取小于nums[i]的最大j
                # dp[i] 应该等于 max{dp[j]} 对应的那个 dp[j] + 1,且只增加一次, 前提是nums[j] < nums[i]
                dp[i] = dp[j] + 1

        res = max(res, dp[i])

    return res

字符串中最长公共子序列(LCS):

  • leecode1143 LongestCommonSubsequence

给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列。
一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。两个字符串的「公共子序列」是这两个字符串所共同拥有的子序列。
若这两个字符串没有公共子序列,则返回 0。

实例如下:

输入:text1 = “abcde”, text2 = “ace”
输出:3
解释:最长公共子序列是 “ace”,它的长度为 3。

  • 1.dp定义

定义dp[i][j] 是字符串前缀s1[:i]与字符串s2[:j]得到的最长公共子串长度

  • 2.dp初始化

dp[i,j] = 0

  • 3.递推公式
if s1[i-1] == s2[j-1]:
	# 当前字符相等时,在dp[i-1][j-1]的基础上加1
	dp[i][j] = dp[i-1][j-1] + 1
else:
	dp[i][j] = max(dp[i][j-1], dp[i-1][j])

最长回文子序列:

  • leetcode516 longestPalindromeSubseq

最长回文子序列
bbbab 返回4

def longestPalindromeSubseq(self, s):
    """
    :type s: str
    :rtype: int
    """
    # 1. dp定义
    # 定义dp[i][j]为子串s[i:j]中包含的最长回文子串的长度
    n = len(s)
    dp = [[0 for j in range(n)] for i in range(n)]

    # 2.dp初始化 
    # dp[i][i] = 1
    for i in range(n):
        dp[i][i] = 1

    # 3.dp递推
    for j in range(1, n):
        for i in range(j-1, -1, -1): #注意递推顺序
            if s[i] == s[j]:
                # 此时结果为子串s[i+1:j-1]中包含的最长回文子串的长度加2
                dp[i][j] = dp[i+1][j-1] + 2
            else:
                dp[i][j] = max(dp[i+1][j], dp[i][j-1])

    return dp[0][n-1]

最大连续子序列和

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [−2,1,−3,4,−1,2,1,−5,4], the contiguous subarray [4,−1,2,1] has the largest sum = 6.

  • 1.dp定义

let dp[i] be the maximum subarray for an array with i elements.
即定义dp[i]为前i个元素的最大连续子序列和。

  • 2.dp初始化

dp[0] = 0
dp[1] = nums[0]

  • 3.dp递推

dp[i] = { dp[n-1] > 0 ? dp[n-1] : 0 } + nums[n-1]

更多精彩文章,欢迎关注公众号“Li的白日呓语”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值