300.最长递增子序列
给你一个整数数组 nums
,找到其中最长严格递增子序列的长度。
子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7]
是数组 [0,3,1,6,2,2,7]
的
子序列
难点:状态转移方程
- 状态转移方程
位置i 的 最长升序子序列 等于 j 从0到i-1各个位置的最长升序子序列 + 1 的最大值。
所以:if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);
如果nums[i] < 所有的 nums[j],那不是取 初始值1了吗?所以这里dp[i]表示的是考虑nums[:i]时,所选序列中包含当前数字时的最长上升子序列长度,而非考虑nums[:i]时的最长上升子序列长度,所以还要用result记录当亲最长上升子序列长度
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
if len(nums) <= 1:
return len(nums)
dp = [1] * len(nums)
result = 1
for i in range(1, len(nums)):
for j in range(0, i):
if nums[i] > nums[j]:
dp[i] = max(dp[i], dp[j] + 1)
result = max(result, dp[i]) #取长的子序列
return result
674. 最长连续递增序列
class Solution:
def findLengthOfLCIS(self, nums: List[int]) -> int:
dp = [1] * len(nums)
result = 1
for i in range(1, len(nums)):
if nums[i] > nums[i-1]:
dp[i] = dp[i-1] + 1
result = max(result, dp[i])
return result
718. 最长重复子数组
给两个整数数组 nums1
和 nums2
,返回 两个数组中 公共的 、长度最长的子数组的长度 。
难点:构造动态规划数组
dp[i][j] :以A[i - 1]为结尾的,和以B[j - 1]为结尾的子数组中,最长重复子数组长度。
根据dp[i][j]的定义,dp[i][j]的状态只能由dp[i - 1][j - 1]推导出来。
即当A[i - 1] 和B[j - 1]相等的时候,dp[i][j] = dp[i - 1][j - 1] + 1;
二维:
class Solution:
def findLength(self, nums1: List[int], nums2: List[int]) -> int:
result = 0
dp = [[0] * (len(nums2) + 1) for _ in range(len(nums1) + 1)]
for i in range(1, len(nums1)+1):
for j in range(1, len(nums2)+1):
if nums1[i-1] == nums2[j-1]:
dp[i][j] = dp[i-1][j-1] + 1
if result < dp[i][j]:
result = dp[i][j]
return result
一维:
class Solution:
def findLength(self, nums1: List[int], nums2: List[int]) -> int:
result = 0
dp = [0] * (len(nums2) + 1)
for i in range(1, len(nums1)+1):
# 记录dp[0]
pre = 0
for j in range(1, len(nums2)+1):
cur = dp[j]
if nums1[i-1] == nums2[j-1]:
# dp[j] = dp[j-1] + 1 这里不对,因为要取二维的时候dp[i-1][j-1]的值,这里可能到dp[i][j-1]的时候变成了0,即当前行dp[j-1] = 0, 而不是dp[j-1]保留的上一行的值。
dp[j] = pre + 1 # 这里pre代表的是dp[j-1]改变前的值
else:
dp[j] = 0
pre = cur
if result < dp[j]:
result = dp[j]
return result
1143.最长公共子序列
给定两个字符串 text1
和 text2
,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列,返回 0
。
一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
- 例如,
"ace"
是"abcde"
的子序列,但"aec"
不是"abcde"
的子序列。
两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。
难点:确定动态规划数组
dp[i][j]:字符串text1[: i]与字符串text2[:j]的最长公共子序列长度
class Solution:
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
dp = [[0] * (len(text2) + 1) for _ in range(len(text1) + 1)]
for i in range(1, len(text1)+1):
for j in range(1, len(text2)+1):
if text1[i-1] == text2[j-1]:
dp[i][j] = dp[i-1][j-1] + 1
else:
dp[i][j] = max(dp[i][j-1], dp[i-1][j])
return dp[-1][-1]
1035.不相交的线
在两条独立的水平线上按给定的顺序写下 nums1
和 nums2
中的整数。
现在,可以绘制一些连接两个数字 nums1[i]
和 nums2[j]
的直线,这些直线需要同时满足:
-
nums1[i] == nums2[j]
- 且绘制的直线不与任何其他连线(非水平线)相交。
请注意,连线即使在端点也不能相交:每个数字只能属于一条连线。
以这种方法绘制线条,并返回可以绘制的最大连线数。
同上一题