Day53| 1143.最长公共子序列、1035.不相交的线 、 53. 最大子序和 动态规划
发布人:shili8
发布时间:2024-12-29 00:03
阅读次数:0
**Day53 |1143. 最长公共子序列、1035. 不相交的线、53. 最大子序和**
在本篇博客中,我们将讨论三个动态规划问题:最长公共子序列(Longest Common Subsequence)、不相交的线(Non-Intersecting Lines)和最大子序和(Maximum Subarray Sum)。这些问题都涉及到如何找到一个序列或一组元素之间的最优解。
###1. 最长公共子序列**1143. 最长公共子序列**
给定两个字符串 `s1` 和 `s2`,我们需要找到它们的最长公共子序列(LCS)。这意味着我们需要找出两个字符串中共同出现的最大子串。
#### 动态规划解决方案我们可以使用动态规划来解决这个问题。我们创建一个2D 数组 `dp`,其中 `dp[i][j]` 表示 `s1` 的前 `i` 个字符和 `s2` 的前 `j` 个字符的最长公共子序列。
def longestCommonSubsequence(s1, s2): m, n = len(s1), len(s2) dp = [[0] * (n +1) for _ in range(m +1)] for i in range(1, m +1): for j in range(1, n +1): if s1[i -1] == s2[j -1]: dp[i][j] = dp[i -1][j -1] +1 else: dp[i][j] = max(dp[i -1][j], dp[i][j -1]) return dp[m][n]
####代码注释* 我们首先创建一个 `dp` 数组,大小为 `(m +1) x (n +1)`,其中 `m` 和 `n` 是 `s1` 和 `s2` 的长度。
* 然后,我们遍历 `s1` 和 `s2` 的所有字符,并更新 `dp` 数组。我们检查当前字符是否相同,如果相同,则更新 `dp[i][j]` 为 `dp[i -1][j -1] +1`,否则取 `dp[i -1][j]` 和 `dp[i][j -1]` 的最大值。
* 最后,我们返回 `dp[m][n]` 作为最长公共子序列的长度。
###2. 不相交的线**1035. 不相交的线**
给定一个点集 `points`,我们需要找到不相交的线段数。两个线段不相交当且仅当它们没有公共点。
#### 动态规划解决方案我们可以使用动态规划来解决这个问题。我们创建一个2D 数组 `dp`,其中 `dp[i][j]` 表示第 `i` 个线段和第 `j` 个线段是否不相交。
def maxUncrossedLines(points): n = len(points) dp = [[0] * n for _ in range(n)] for i in range(n): for j in range(i, n): if points[i][0] == points[j][0]: dp[i][j] =1 elif points[i][0] < points[j][0]: dp[i][j] = dp[i +1][j] else: dp[i][j] = dp[i][j -1] return sum(dp[i][i] for i in range(n))
####代码注释* 我们首先创建一个 `dp` 数组,大小为 `n x n`,其中 `n` 是点集的长度。
* 然后,我们遍历点集,并更新 `dp` 数组。我们检查当前线段是否不相交,如果不相交,则更新 `dp[i][j]` 为1,否则取 `dp[i +1][j]` 和 `dp[i][j -1]` 的值。
* 最后,我们返回 `dp` 中所有对角元素的和作为不相交线段数。
###3. 最大子序和**53. 最大子序和**
给定一个整数数组 `nums`,我们需要找到最大子序列和。这个问题等价于找出最长递增子序列(LIS)的长度。
#### 动态规划解决方案我们可以使用动态规划来解决这个问题。我们创建一个1D 数组 `dp`,其中 `dp[i]` 表示以 `nums[i]` 为结尾的最大子序和。
def maxSubArray(nums): n = len(nums) dp = [0] * (n +1) for i in range(1, n +1): if nums[i -1] > dp[i -1]: dp[i] = nums[i -1] else: dp[i] = dp[i -1] return max(dp[1:])
####代码注释* 我们首先创建一个 `dp` 数组,大小为 `(n +1)`,其中 `n` 是数组的长度。
* 然后,我们遍历数组,并更新 `dp` 数组。我们检查当前元素是否大于前一个最大子序和,如果大于,则更新 `dp[i]` 为当前元素值,否则取前一个最大子序和。
* 最后,我们返回 `dp` 中所有非零元素的最大值作为最大子序和。
以上就是本篇博客中讨论的三个动态规划问题:最长公共子序列、不相交的线和最大子序和。这些问题都涉及到如何找到一个序列或一组元素之间的最优解。