动态规划总结(一)

刷了动态规划的几个题,来总结下方法。
动态规划一般都有递推式,如果找到第n个和第n-1个之间的关系(或者还包含第n-2个),那么整个思路就会很清晰了,动态规划问题一般都是寻找最优路径类的问题。

leetcode 53. 最大子序和

用tem[i]来表示第i个点的最大子序和,那么tem[i]=max(tem[i-1]+nums[i],nums[i])

class Solution(object):
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        res=nums[0]
        tem=nums[0]
        for i in range(1,len(nums)):
            tem=max(tem+nums[i],nums[i])
            if tem>res:
                res=tem
        return res

leetcode 62. 不同路径

《动态规划总结(一)》 image.png

设定一个数组的dp[m][n] ,对于dp[i][j]表示到节点[i][j]有多少种不同的路径,dp[i][j]=dp[i-1][j]+dp[i][j-1],因为只能向下或者向右走

class Solution:
    def uniquePaths(self, m, n):
        """
        :type m: int
        :type n: int
        :rtype: int
        """
        if m<=0 and n<=0:
            return 0
        dp=[[0]*n]*m
        for i in range(m):
            dp[i][0]=1
        for i in range(n):
            dp[0][i]=1
        for i in range(1,m):
            for j in range(1,n):
                dp[i][j]=dp[i][j-1]+dp[i-1][j]
        return dp[m-1][n-1]

leetcode 63. 不同路径 II

《动态规划总结(一)》 image.png

难度稍有增加,增加障碍物后,如果障碍物节点为[i][j],那么dp[i][j]=0,因为没有路可以到达这个节点。

class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid):
        """
        :type obstacleGrid: List[List[int]]
        :rtype: int
        """
        if len(obstacleGrid)==0:
            return 0
       
        m=len(obstacleGrid)
        n=len(obstacleGrid[0])
        
        dp = [[0]*n]*m
       
        for i in range(0,m):
            for j in range(0,n):
                if obstacleGrid[i][j]==1:
                    dp[i][j]=0
                else:
                    if i>0 and j==0:
                        dp[i][j] = dp[i-1][j] 
                    elif i==0 and j>0:
                        dp[i][j] = dp[i][j-1]
                    elif i==0 and j==0:
                        dp[i][j]=1
                    else:
                        dp[i][j] = dp[i-1][j] + dp[i][j-1]
        return dp[m-1][n-1]

leetcode 70. 爬楼梯

《动态规划总结(一)》 image.png

这个题的规律在于第n个台阶可以由第n-1个台阶爬一阶,还可以由第n-2阶台阶爬两阶得到,res[n]=res[n-1]+res[n-2]

class Solution(object):
    def climbStairs(self, n):
        """
        :type n: int
        :rtype: int
        """
        a=1
        b=2
        res=0
        if n==1:
            return a
        elif n==2:
            return b
        elif n>=3:
            for i in range(3,n+1):
                res=a+b
                a=b
                b=res
        return res

leetcode 91. 解码方法

《动态规划总结(一)》 image.png

这个题我写的很复杂,先考虑了如果s的长度<=1的两种情况,然后考虑了len(s)>=2的时候,那么s[i]!=’0’的话,res[i]=res[i-1], 如果int(s[i-1:i+1])<=26,那么res[i]还有再加上res[i-2],也就是说把s[i]当做一个单独的数解析是一种情况,把s[i]和是s[i]和s[i-1]放在一起又是一种情况,就是要考虑这两种情况。如果s[i]==’0’,那么就看s[i-1]<=2,如果s[i]<=2,那么res[i]=res[i-2], 否则return 0,因为没有数字可以和0组合。所以把思路梳理成if … then…,就清晰了。

class Solution:
    def numDecodings(self, s):
        """
        :type s: str
        :rtype: int
        """
        if len(s)==0:
            return 0
        if len(s)==1:
            if s=="0":
                return 0
            return 1 #在这句话之前都只是考虑长度小于1的情况
        res=[0]*len(s)
        if s[0]!="0":
            res[0]=1
        else:
            return 0
        if s[1]!="0":
            res[1]=1
        else:
            res[1]=0
        if int(s[:2])<=26 and int(s[:2])>0:
            res[1]=res[1]+1
         #在这之前准备好res[0] res[1]  
        for i in range(2,len(s)):
            if s[i]!="0":
                res[i]=res[i-1]
                if  s[i-1]!='0' and int(s[i-1:i+1])<=26:
                    res[i]+=res[i-2]
            else:
                if int(s[i-1:i+1])<=26 and int(s[i-1:i+1])>0:
                    res[i]=res[i-2]
                else:
                    return 0
        return res[-1]

leetcode 95 不同的二叉搜索树

《动态规划总结(一)》 image.png

实际上是求卡特兰数列,让1-n之间的数每个数都做一次根节点,左子树是比根节点小的数,右子树是比根节点大的数,以n=3为例,
Count[3] = Count[0]Count[2] (1为根的情况) + Count[1]Count[1] (2为根的情况) + Count[2]*Count[0] (3为根的情况)

本文来自 qqxx6661 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/qqxx6661/article/details/76285972?utm_source=copy

class Solution:
    def numTrees(self, n):
        """
        :type n: int
        :rtype: int
        """
        dp=[1,1,2]#指的是dp[0] dp[1] dp[2]
        if n<=2:
            return dp[n]
        dp+=[0 for i in range(n-2)]
        for i in range(3,n+1):
            for j in range(0,i):
                dp[i]+=dp[j]*dp[i-1-j]
        return dp[n]

leetcode 94:

请看这篇解答吧,我一开始没啥思路https://blog.csdn.net/fuxuemingzhu/article/details/80778651

《动态规划总结(一)》 image.png

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def generateTrees(self, n):
        """
        :type n: int
        :rtype: List[TreeNode]
        """
        if n==0:
            return []
        return self.dfs(1,n)
    def dfs(self,s,e):
        if s>e:
            return [None]
        res=[]
        for tem in range(s,e+1):
            left=self.dfs(s,tem-1)
            right=self.dfs(tem+1,e)
            
            for i in left:
                for j in right:
                    root=TreeNode(tem)
                    root.left=i
                    root.right=j
                    res.append(root)
        return res

怕什么真理无穷,进一寸有一寸的欢喜。—–胡适

    原文作者:贪心算法
    原文地址: https://www.jianshu.com/p/9572a9575c4c
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞