代码随想录算法训练营day44| 1143.最长公共子序列 1035.不相交的线 53. 最大子序和 392.判断子序列

学习资料:https://programmercarl.com/1143.最长公共子序列.html#算法公开课

动态规划系列之子序列
其实有些用贪心也可解

学习记录:
1143.最长公共子序列(dp[i][j]是代表的i-1和j-1为止的两个片段的最长公共子序列,原因是为了更好的初始化;比如当dp[0][0]代表的到-1和-1的两个片段,那肯定不存在,所以两个片段无交集,值为0,否则还得仔细考虑两者交集)

点击查看代码
class Solution(object):
    def longestCommonSubsequence(self, text1, text2):
        """
        :type text1: str
        :type text2: str
        :rtype: int
        """
        # dp[i][j]代表num1中到i-1和nums2中到j-1为止的两段的最长公共子序列长度
        # 构造二维dp数组
        dp = [[0]*(len(text2)+1) for _ in range((len(text1)+1))]
        # 初始化也是0,跳过

        # 开始遍历
        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   # 由左上角的值加1
                else:
                    dp[i][j] = max(dp[i-1][j], dp[i][j-1])       # 由左边和上边的值确定
        return dp[len(text1)][len(text2)]  # 右下角的值
        

1035.不相交的线(与最长公共子序列的解法一致)

点击查看代码
class Solution(object):
    def maxUncrossedLines(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: int
        """
        # 与最长公共子序列解法一致
        # dp[i][j]是nums1的i及之前和nums2的j及之前的最长公共子序列
        dp = [[0]*(len(nums2)+1) for _ in range(len(nums1)+1)]
        # 初始化也是把左边和上边设置为0

        # 开始遍历
        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
                else:
                    dp[i][j] = max(dp[i-1][j], dp[i][j-1])
        return dp[len(nums1)][len(nums2)]

53.最大子序和(当涉及连续条件时,就用一维数组,比较i-1与i;有动态规划和贪心两种解法,基本思想一样,当前面和为负(前面的和+nums[i]<nums[i])就舍弃,才能避免拖累下一个数;一维dp数组,dp[i]代表到i为止的连续子序列的最大和;最大和可能在遍历的中间位置,记得随时更新记录)

点击查看代码
class Solution(object):
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        # 动态规划解法
        # dp[i]代表nums以i为结尾时的连续子数组的最大和
        dp = [[0] for _ in range(len(nums))]
        # 初始化
        dp[0] = nums[0]
        # 更新最大和
        result = nums[0]
        # 开始遍历
        for i in range(1, len(nums)):
            # 若前几个数的和为整数,那现在的和就加上nums[i];若和为负数就舍弃,只保留nums[i]
            dp[i] = max(dp[i-1]+nums[i], nums[i])
            result = max(dp[i], result)
        return result

        # # 解法一:贪心算法吗?怎么不做记录
        # if not nums:
        #     return 0
        # dp = [nums[0]]
        # res=dp[0]
        # for i in range(1, len(nums)):
        #     dp.append(max(dp[i-1]+nums[i], nums[i]))
        #     if dp[-1]>res:
        #         res=dp[-1]
        # return res

392.判断子序列(这道题也与最大公共子序列解法一致,具体思路:当两者的最大公共子序列等于前者长度时,说明前者是后者的子序列)

点击查看代码
class Solution(object):
    def isSubsequence(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        # 此题解法基于最长公共子序列,如果两者的最长公共子序列的长度正好等于s的长度,那就说明s就是t的子序列
        # dp[i][j]代表字符串s的前i-1段和字符串t的前j-1段的最长公共子序列长度,这里用i-1,j-1是为了后面初始化
        # 构建二维dp数组
        dp = [[0]*(len(t)+1) for _ in range(len(s)+1)]
        # 初始化
        # 就是第一行和第一列的值都能为零,因为比如dp[0][j]是s的前-1段和t的前j-1段,-1段肯定不存在所以两者公共为0;
        # 但是如果前面dp[i][j]设置为前i段和前j段,这里第一行第一列就可能非零了,那很麻烦的。

        # 开始遍历
        for i in range(1, len(s)+1):
            for j in range(1, len(t)+1):
                # 由于dp[i-1][j-1]是到i-2和到j-2的公共子序列长度,那如果i-1和j-1处正好相等,那公共子序列长度就再加1
                if s[i-1] == t[j-1]:
                    dp[i][j] = dp[i-1][j-1] + 1
                else:
                    dp[i][j] = dp[i][j-1]
        if dp[len(s)][len(t)] == len(s):   # 如果公共子序列长度等于s字符串长度,说明s是t的子序列
            return True
        else:
            return False

        

PS:今天还是子序列问题,比昨天听的更明白了。
下小雨就像吃点热乎的,今天吃了好吃的排骨米线,辣辣的火鸡面、芝士牛肉石锅、章鱼小丸子,很满足,很撑
2024.11.11 19:48左右 樊某驾车闯入珠海市体育中心,造成35人死亡、43人受伤。

posted @   Tristan241001  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示