代码随想录算法训练营第五十天| LeetCode300.最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组、1143.最长公共子序列

300.最长递增子序列

题目描述: 300.最长递增子序列.

解法

dp

python 复制代码
class Solution(object):
    def lengthOfLIS(self, nums):
        if len(nums) <= 1:
            return len(nums)
        dp = [1] * len(nums)
        res = 0
        for i in range(1,len(nums)):
            for j in range(i):
                if nums[j] < nums[i]:
                    dp[i] = max(dp[i],dp[j]+1)
            res = max(res,dp[i])
        return res

考虑的是:以当前节点为终点的递增序列,最长为多少。

674. 最长连续递增序列

题目描述: 674. 最长连续递增序列.

解法

dp

python 复制代码
class Solution(object):
    def findLengthOfLCIS(self, nums):
        if len(nums) <= 1:
            return len(nums)
        dp = [1] * len(nums)
        res = 0
        for i in range(1,len(nums)):
            if nums[i-1] < nums[i]:
                dp[i] = dp[i-1] + 1
            res = max(res,dp[i])
        return res

718. 最长重复子数组

题目描述: 718. 最长重复子数组.

解法

二维dp

python 复制代码
class Solution:
    def findLength(self, nums1: List[int], nums2: List[int]) -> int:
        dp = [[0] * (len(nums1)+1) for _ in range(len(nums2)+1)]
        res = 0
        for i in range(1,len(nums2)+1):
            for j in range(1,len(nums1)+1):
                if nums2[i-1] ==  nums1[j-1]:
                    dp[i][j] = dp[i-1][j-1] + 1
                res = max(res,dp[i][j])
        return res

滚动dp

python 复制代码
class Solution(object):
    def findLength(self, nums1, nums2):
        dp = [0]*(len(nums1)+1)
        res = 0
        for i in range(1,len(nums2)+1):
            for j in range(len(nums1),0,-1):
                if nums2[i-1] == nums1[j-1]:
                    dp[j] = dp[j-1] + 1
                else:
                    dp[j] = 0
                res = max(res,dp[j])
        return res

只要dp[i][j]是由dp[i-1][j]或者dp[i-1][j-1]决定的,就可以使用滚动数组

本体的主要思路就是,遍历每个字符串的每一位,然后对比以该位为终点的相同的子串有多少位,如果该位相同,那就在前一位的基础上+1,否则的话,就置为0

1143.最长公共子序列

题目描述: 1143.最长公共子序列.

解法

二维dp

python 复制代码
class Solution(object):
    def longestCommonSubsequence(self, text1, text2):
        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])
                res = max(res,dp[i][j])
        return dp[len(text1)][len(text2)]

需要考虑两个字符串任意减少一个的情况

子序列和子数组不同的就在于,子数组一定是连续的,所以考虑dp[i][j]时一定要考虑dp[i-1][j-1]

但是子序列就不一样了,如果dp[i][j]不能由dp[i-1][j-1]得到,那就得考虑每个单词各削减一位的情况了。

同样,因为是子序列,所以不需要考虑最长在哪,返回最后的dp就一定是最长的子序列长度

滚动dp

python 复制代码
class Solution(object):
    def longestCommonSubsequence(self, text1, text2):
        dp = [0]* (len(text1)+1)
        res = 0
        for i in range(1,len(text2)+1):
            pre = 0
            for j in range(1,len(text1)+1):
                cur = dp[j]
                if text1[j-1] == text2[i-1]:
                    dp[j] = pre + 1
                else:
                    dp[j] = max(dp[j],dp[j-1])
                pre = cur
        return dp[len(text1)]

当使用滚动dp时,就要考虑当前的这个元素和什么有关,如果仅是和上有关,那就可以将dp的内容倒序更新,但是如果和左也有关系,那就只能正序更新,然后记录更新之前的当前元素。

相关推荐
艾莉丝努力练剑7 分钟前
【LeetCode&数据结构】单链表的应用——反转链表问题、链表的中间节点问题详解
c语言·开发语言·数据结构·学习·算法·leetcode·链表
_殊途2 小时前
《Java HashMap底层原理全解析(源码+性能+面试)》
java·数据结构·算法
珊瑚里的鱼5 小时前
LeetCode 692题解 | 前K个高频单词
开发语言·c++·算法·leetcode·职场和发展·学习方法
秋说6 小时前
【PTA数据结构 | C语言版】顺序队列的3个操作
c语言·数据结构·算法
lifallen6 小时前
Kafka 时间轮深度解析:如何O(1)处理定时任务
java·数据结构·分布式·后端·算法·kafka
liupenglove7 小时前
自动驾驶数据仓库:时间片合并算法。
大数据·数据仓库·算法·elasticsearch·自动驾驶
python_tty8 小时前
排序算法(二):插入排序
算法·排序算法
然我8 小时前
面试官:如何判断元素是否出现过?我:三种哈希方法任你选
前端·javascript·算法
F_D_Z8 小时前
【EM算法】三硬币模型
算法·机器学习·概率论·em算法·极大似然估计
秋说9 小时前
【PTA数据结构 | C语言版】字符串插入操作(不限长)
c语言·数据结构·算法