代码随想录算法训练营Day43
力扣300.最长递增子序列
力扣674.最长连续递增子序列【easy】
力扣1143.最长公共子序列【medium】
力扣718.最长重复子数组【medium】
一、力扣300.最长递增子序列【medium】
题目链接:力扣300.最长递增子序列
视频链接:代码随想录
题解链接:灵茶山艾府
1、思路
- 构造选 n u m s [ i ] nums[i] nums[i] 为子列的末尾元素,再遍历[1,i) ,选出 n u m s [ j ] < n u m s [ i ] nums[j] < nums[i] nums[j]<nums[i]
- d f s ( i ) dfs(i) dfs(i):表示以 n u m s [ i ] nums[i] nums[i] 结尾的LIS长度
2、代码
1)记忆化搜索
- 时间复杂度: O ( n 2 ) O(n^2) O(n2)
- 空间复杂度: O ( n ) O(n) O(n)
class Solution:def lengthOfLIS(self, nums: List[int]) -> int:@cachedef dfs(i:int) -> int:res = 0for j in range(i):if nums[j] < nums[i]:res = max(res, dfs(j))return res + 1return max(dfs(i) for i in range(len(nums)))
- 时间复杂度: O ( n 2 ) O(n^2) O(n2)
- 空间复杂度: O ( n ) O(n) O(n)
class Solution:def lengthOfLIS(self, nums: List[int]) -> int:n = len(nums)f = [0] * n for i, x in enumerate(nums):for j, y in enumerate(nums[: i]):if y < x:f[i] = max(f[i], f[j])f[i] += 1return max(f)
- 时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn),二分法是 l o g n logn logn
- 空间复杂度: O ( n ) O(n) O(n)
class Solution:def lengthOfLIS(self, nums: List[int]) -> int:g = []for x in nums:j = bisect_left(g, x)if j == len(g):g.append(x)else:g[j] = xreturn len(g)
3、代码问题
二、力扣674.最长连续递增子序列【easy】
题目链接:力扣最长连续递增子序列
视频链接:代码随想录
1、思路
- 这题是连续!
- 可以用贪心更简单!!
- 时间复杂度: O ( n ) O(n) O(n)
2、代码
1)贪心
class Solution:def findLengthOfLCIS(self, nums: List[int]) -> int:n = len(nums)ans = 1count = 1for i in range(1, n):if nums[i - 1] <nums[i]:count += 1ans = max(count, ans)else:count = 1return ans
2)dp:动态规划
class Solution:def findLengthOfLCIS(self, nums: List[int]) -> int:n = len(nums)ans = 1f = [1] * n for i in range(1, n):if nums[i - 1] < nums[i]:f[i] = f[i - 1] + 1ans = max(f[i], ans)return ans
三、力扣1143.最长公共子序列【medium】
题目链接:力扣1143.最长公共子序列
视频链接:代码随想录
题解链接:灵茶山艾府
1、思路
- 时间复杂度: O ( n m ) O(nm) O(nm)
2、代码
1)记忆化搜索
class Solution:def longestCommonSubsequence(self, text1: str, text2: str) -> int:m, n = len(text1), len(text2)@cachedef dfs(i:int, j:int) -> int:if i < 0 or j < 0 :return 0if text1[i] == text2[j] :return dfs(i - 1, j - 1) + 1else:return max(dfs(i - 1, j), dfs(i, j - 1))return dfs(m - 1, n - 1)
2)dp
class Solution:def longestCommonSubsequence(self, text1: str, text2: str) -> int:m, n = len(text1), len(text2)f = [[0] * (n + 1) for _ in range(m + 1)]for i, x in enumerate(text1):for j, y in enumerate(text2):f[i + 1][j + 1] = f[i][j] + 1 if x == y else max(f[i + 1][j], f[i][j + 1])return f[m][n]
3)空间优化:一个数组
class Solution:def longestCommonSubsequence(self, text1: str, text2: str) -> int:m, n = len(text1), len(text2)f = [0] * (n + 1) for x in text1:pre = 0for j, y in enumerate(text2):tmp = f[j + 1]f[j + 1] = pre + 1 if x == y else max(f[j], f[j + 1])pre = tmp #保证 pre 是 f 数组上一行的数据,不是当前行的数据。return f[n]
四、力扣718.最长重复子数组【medium】
题目链接:力扣
left =x300
视频链接:代码随想录
1、思路
- 时间复杂度: O ( m ∗ n ) O(m * n) O(m∗n)
2、代码
1)记忆化搜索
class Solution:def findLength(self, nums1: List[int], nums2: List[int]) -> int:m, n = len(nums1), len(nums2)ans = 0@cachedef dfs(i:int, j:int) -> int:if i < 0 or j < 0:return 0if nums1[i] == nums2[j]:count = dfs(i - 1, j - 1) + 1else:count = 0nonlocal ansans = max(count, ans)return countfor i in range(m):for j in range(n):dfs(i, j)return ans
2)dp
class Solution:def findLength(self, nums1: List[int], nums2: List[int]) -> int:m, n = len(nums1), len(nums2)ans = 0f = [[0] * (n + 1) for _ in range(m + 1)]for i, x in enumerate(nums1):for j, y in enumerate(nums2):# 当前字符相等时,继承左上方值 +1,否则重置为 0if x == y:f[i + 1][j + 1] = f[i][j] + 1ans = max(f[i + 1][j + 1], ans)else:f[i + 1][j + 1] = 0 # 不连续时直接置零return ans
3)空间优化:一个数组
class Solution:def findLength(self, nums1: List[int], nums2: List[int]) -> int:m, n = len(nums1), len(nums2)ans = 0f = [0] * (n + 1) for i, x in enumerate(nums1):pre = 0for j, y in enumerate(nums2):tmp = f[j + 1]# 当前字符相等时,继承左上方值 +1,否则重置为 0if x == y:f[j + 1] = pre + 1ans = max(f[j + 1], ans)else:f[j + 1] = 0 # 不连续时直接置零pre = tmpreturn ans