代码随想录算法学习心得 45 | 300.最长递增子序列、674.最长连续递增序列、718.最长重复子数组...
发布人:shili8
发布时间:2024-12-22 02:36
阅读次数:0
**代码随想录算法学习心得45**
在本篇文章中,我们将讨论四个经典的动态规划问题:最长递增子序列(Longest Increasing Subsequence, LIS)、最长连续递增序列(Longest Continuous Increasing Sequence, LCIS)、最长重复子数组(Longest Repeated Subarray, LRS)和最长公共子序列(Longest Common Subsequence, LCS)。这些问题都是经典的动态规划问题,能够帮助我们提高对算法设计和实现的理解。
### 最长递增子序列 (LIS)
给定一个整数数组 `nums`,要求找到其中最长的递增子序列。例如,如果输入 `[10,9,2,5,3,7,101,18]`,输出应该是 `[2,3,7,101]`。
#### 动态规划解决方案我们可以使用动态规划来解决这个问题。具体来说,我们将维护一个长度为 `n` 的数组 `dp`,其中 `dp[i]` 表示序列 `nums[0..i-1]` 中最长递增子序列的长度。
def longest_increasing_sequence(nums): n = len(nums) dp = [1] * n 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)
#### 时间复杂度分析时间复杂度为 O(n^2),因为我们需要对每个元素进行 O(n) 次比较。
### 最长连续递增序列 (LCIS)
给定一个整数数组 `nums`,要求找到其中最长的连续递增子序列。例如,如果输入 `[1,3,5,7]`,输出应该是 `[1,3,5,7]`。
#### 动态规划解决方案我们可以使用动态规划来解决这个问题。具体来说,我们将维护一个长度为 `n` 的数组 `dp`,其中 `dp[i]` 表示序列 `nums[0..i-1]` 中最长连续递增子序列的长度。
def longest_continuous_increasing_sequence(nums): n = len(nums) dp = [1] * n for i in range(1, n): if nums[i] > nums[i -1]: dp[i] = dp[i -1] +1 return max(dp)
#### 时间复杂度分析时间复杂度为 O(n),因为我们只需要对每个元素进行一次比较。
### 最长重复子数组 (LRS)
给定两个整数数组 `nums1` 和 `nums2`,要求找到其中最长的重复子数组。例如,如果输入 `[1,2,3]` 和 `[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]`,输出应该是 `[1,2,3]`。
#### 动态规划解决方案我们可以使用动态规划来解决这个问题。具体来说,我们将维护两个长度为 `n` 的数组 `dp1` 和 `dp2`,其中 `dp1[i]` 表示序列 `nums1[0..i-1]` 中最长重复子数组的长度,`dp2[j]` 表示序列 `nums2[0..j-1]` 中最长重复子数组的长度。
def longest_repeated_subarray(nums1, nums2): n = len(nums1) m = len(nums2) dp1 = [0] * (n +1) dp2 = [0] * (m +1) for i in range(1, n +1): for j in range(1, m +1): if nums1[i -1] == nums2[j -1]: dp1[i] = max(dp1[i], dp2[j] +1) dp2[j] = max(dp2[j], dp1[i]) return max(max(dp1), max(dp2))
#### 时间复杂度分析时间复杂度为 O(n * m),因为我们需要对每个元素进行 O(m) 次比较。
### 最长公共子序列 (LCS)
给定两个整数数组 `nums1` 和 `nums2`,要求找到其中最长的公共子序列。例如,如果输入 `[1,2,3]` 和 `[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]`,输出应该是 `[1,2,3]`。
#### 动态规划解决方案我们可以使用动态规划来解决这个问题。具体来说,我们将维护两个长度为 `n` 的数组 `dp1` 和 `dp2`,其中 `dp1[i]` 表示序列 `nums1[0..i-1]` 中最长公共子序列的长度,`dp2[j]` 表示序列 `nums2[0..j-1]` 中最长公共子序列的长度。
def longest_common_subsequence(nums1, nums2): n = len(nums1) m = len(nums2) dp1 = [0] * (n +1) dp2 = [0] * (m +1) for i in range(1, n +1): for j in range(1, m +1): if nums1[i -1] == nums2[j -1]: dp1[i] = max(dp1[i], dp2[j] +1) dp2[j] = max(dp2[j], dp1[i]) return max(max(dp1), max(dp2))
#### 时间复杂度分析时间复杂度为 O(n * m),因为我们需要对每个元素进行 O(m) 次比较。
综上所述,我们可以使用动态规划来解决最长递增子序列、最长连续递增序列、最长重复子数组和最长公共子序列等问题。这些问题都是经典的动态规划问题,能够帮助我们提高对算法设计和实现的理解。
**参考资料**
* 《算法导论》第三版* 《数据结构与算法分析》第二版