leetcode300(不连续)[1143,1035,583,392(不需res),115]//674(连续)718(注意dp设置)

300

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        dp=[1]*(len(nums))
        if len(nums)<=1:
            return len(nums)
        res=0
        for j in range(1,len(nums)):#因为i要比j小,所以j应该从1开始。
            for i in range(j):
                if nums[j]>nums[i]:
                    dp[j]=max(dp[j],dp[i]+1)#不是为了比较两者大小,而是要取dp[i]+1的最大值。
                if dp[j]>res:res=dp[j]#最长子序列并不一定出现在dp的最后一个。所以我们要判断记录一下,最终
            #选取max(dp)。
        return res
    '''分析过程:
    1、dp含义:代表当下标为j的时候,最长子序列长度
    2、递推公式。首先我们判断的是最长子序列,所以我们要明确,当nums[j]>nums[i]的时候,说明dp[j]应该更新了,
    但是如果当前的dp[j]如果≥dp[i]+1,就不需要更新,否则更新成为dp[i]+1。这样才能保证dp[j]长度最长。
    3、初始化,因为规定了nums非空,所以无论如何,最长子序列长度最少为1。
    4、遍历顺序,由于dp[j]依赖于dp[i],所以从前往后。
    '''


1143

class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        len1=len(text1)
        len2=len(text2)
        dp=[[0 for _ in range(len2+1)] for _ in range(len1+1)]
        for i in range(1,len1+1):
            for j in range(1,len2+1):
                if text1[i-1]==text2[j-1]:
                    dp[i][j]=dp[i-1][j-1]+1#这一步和718题一样,如果相等就从左上向右下+1.
                else:
                    dp[i][j]=max(dp[i-1][j],dp[i][j-1])
        return dp[-1][-1]
    '''else这里这里我们要处理让该题不连续也可以继续统计最长。#如果两者不相等的话,那么肯定取之前的某个最大的
    公共子序列,那么这个最大子序列可能有两个来源,要么是从其左边来,要么就是从其上方来,取最大者。'''

1035

class Solution:
    def maxUncrossedLines(self, nums1: List[int], nums2: List[int]) -> int:
        len1=len(nums1)
        len2=len(nums2)
        dp=[[0 for _ in range(len2+1)] for _ in range(len1+1)]
        for i in range(1,len1+1):
            for j in range(1,len2+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[-1][-1]
    '''和1143题一模一样,这题的意思就是,在两个数组中,只要数字的相对顺序不变,那么就有几个不相交的直线。'''

583

class Solution:
    def minDistance(self, word1: str, word2: str) -> int:
        len1 = len(word1)
        len2 = len(word2)
        dp = [[0 for _ in range(len2 + 1)] for _ in range(len1 + 1)]
        for i in range(1, len1 + 1):
            for j in range(1, len2 + 1):
                if word1[i - 1] == word2[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 len1+len2-2*dp[-1][-1]
    '''1143同类型的题,最小删除步数,其实就等于,两个字符串的长度和,减去2倍的最长子序列长度就ok了'''

392

class Solution:
    def isSubsequence(self, s: str, t: str) -> bool:
        lens=len(s)
        lent=len(t)
        dp=[[0 for _ in range(lent+1)] for _ in range(lens+1)]
        for i in range(1,lens+1):
            for j in range(1,lent+1):
                if s[i-1]==t[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]==lens
    '''只需要判断两个字符串的最长公共子序列长度是不是和s一样就可以了。如果不一样,一定不是子序列。'''

 115

class Solution:
    def numDistinct(self, s: str, t: str) -> int:
        lens=len(s)
        lent=len(t)
        dp=[[0 for _ in range(lent+1)] for _ in range(lens+1)]
        for i in range(lens+1):
            dp[i][0]=1
        for i in range(1,lens+1):
            for j in range(1,lent+1):
                if s[i-1]==t[j-1]:
                    dp[i][j]=dp[i-1][j-1]+dp[i-1][j]
                else:
                    dp[i][j]=dp[i-1][j]
        return dp[-1][-1]
    '''1、dp代表t在s中出现的个数。
        2、递推公式。和判断子序列有整体架构相似,但是递推公式不同,因为那是求是不是子序列,这是求子序列的个数。
        为什么会有个数差异呢?是因为t的某些元素在s中并不是只有一个,我们需要选择是哪一个。这样问题就来了。
        我们原来如果匹配到s[i-1]==t[j-1],说明当前s元素和t元素相同,我们可以选择他匹配,也可以不选择。
        为什么可以不选择呢?因为t元素在s中不一定是唯一的。那么这就造成了,dp[i][j]的来源是两个,
        一个是左上方,一个是正上方。
        如果不相等,那么当前dp一定和它正上方的dp相同。
        3、初始化,我们判断t是不是s的子序列。所以dp[0][j]说明s是空字符串,都应该为0.
        dp[i][0]说明t是空字符串,肯定是s的子序列。所以初始化为1.dp[0][0]也应该为1.
        4、遍历顺序。当前dp取决于左上方和正上方。正序遍历。'''

674

class Solution:
    def findLengthOfLCIS(self, nums: List[int]) -> int:
        n=len(nums)
        if n<=1:
            return  n
        dp=[1]*n
        res=0
        for i in range(1,n):
            if nums[i]>nums[i-1]:
                dp[i]=dp[i-1]+1
            if dp[i]>res:res=dp[i]
        return res

    '''分析过程:
    1、dp含义:代表当下标为j的时候,连续最长子序列长度
    2、递推公式。首先我们判断的是最长子序列,因为是连续最长子序列所以我们要明确,dp[i]依赖于dp[i-1],当nums[i]>nums[i-1]的时候,说明dp[i]应该更新了,否则我们需要用res记录一下,让这次的结果和以后出现的dp[i]进行比较。这样才能保证dp[j]长度最长。
    3、初始化,因为规定了nums非空,所以无论如何,最长子序列长度最少为1。
    4、遍历顺序,由于dp[i]依赖于dp[i-1],所以从前往后。
    '''


718

class Solution:
    def findLength(self, nums1: List[int], nums2: List[int]) -> int:
        dp=[[0 for _ in range(len(nums2)+1)] for _ in range(len(nums1)+1)]
        res=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矩阵中,就是体现在从左上向右下递增
                    dp[i][j]=dp[i-1][j-1]+1
                if res<dp[i][j]:res=dp[i][j]#同样应该在全dp内找最大,而不是最后一位。所以要放在第二个for内。
        return res

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值