动态规划LeetCode

动态规划题目总结

近日做了一些LeetCode中的动态规划的题目,可以做个总结了!
1322.零钱兑换
2121.买卖股票最佳时机I
3122.买卖股票的最佳时机II
4面试题08.01三步问题
570.爬楼梯
6746.使用最小路径爬楼梯
7343.整数拆分
862.不同路径
963.不同路径II

322.零钱兑换

题目
该题显然是可以用动态规划去做的。不明白的可以看看这篇文章。里面列出了哪些情况是可以用动态规划去做。
动态规划的做题步奏如下
1:确定dp矩阵,并明确dp[i]或者其他形式,但一定要理解其含义是什么,比如此题dp[i]的意思
就是拼出价值为i需要的最少硬币数目
dp = [sys.maxsize-1] * (amount+1)。对dp矩阵每一个值都初始化为无穷大
为什么是amount+1?因为需要一个dp[0]去存储初始化的值

	2:*初始化*,需要对dp矩阵进行初始化,个人理解是动态规划很类似于递归,需要给一个出口,不然
	就一直死循环下去。
	dp[0] = 0,即拼出0元需要最少的硬币数是0

	3:*转移方程*,也是最重要的。
	这题中没有给固定的coins,就拿第一个example来举例吧。
	coins= 【1,2,5】,对dp矩阵每个值进行遍历赋值,dp[i]的值就是dp[i]+1,即加上当前的coin和
dp[coin+i]进行比较哪个比较小。因为计算顺序是从左往右,所以当计算后面i值时候,前面已经有结果了。
	dp[i+coin] = min(dp[coin+i],dp[i]+1)
		dp = [sys.maxsize-1] * (amount+1)#定义一个dp矩阵,分别存放着拼出dp[i]所需最少的硬币个数
        dp[0] = 0 #初始化dp矩阵最开始的元素为0
        for i in range(amount+1):#初始化之后开始最dp数组中每个元素进行赋值
            if dp[i] == sys.maxsize - 1:#如果dp[i]当前元素为无穷,则说明此时无解,进行下轮循环
                continue
            for coin in coins:#若此时dp[i]不是无穷大,则分别添加硬币列表中的硬币进行选择
                if coin + i <= amount:#如果加上此时的硬币还小于amount
                    dp[i+coin] = min(dp[coin+i],dp[i]+1)#比较原始的跟加上一枚之后哪个更小
        if dp[-1] == sys.maxsize -1:return -1#如果循环赋值之后,dp[i]最后一位还是无穷,则无解
        else:return dp[-1]#有解,则返回最后一个数

121.买卖股票最佳时机I

股票
解题思路:
按照正常的思想肯定是在最低价的时候买入,然后在最高价的时候卖出,这样才能使获得的利润最大。
可以设置一个变量minprice用来存储当前所遇到的最低的价格,然后判断当天是卖出股票所能获得的利润大还是不卖获得的利润大。

动态规划解题步奏:							
	1:确定dp矩阵,并明确dp[i]所代表的含义:
		dp[i]:代表着前i天操作股票可以获得的最大收益
	2:初始化dp矩阵:
		dp[0] = 0
	3:状态转移方程
		dp[i] = max( dp[i-1] ,prices[i])-minprice)
		即比较在第i天不卖出股票和根据当天的价格卖出股票,哪个可以获得的收益更大

python代码如下

def maxProfit(self, prices: List[int]) -> int:

        n = len(prices) #价格数组的长度
        if n == 0:return 0 
        dp = [0] * n #初始化dp矩阵
        #dp[i]表示前i天可以获得的最大利润
        
        minprice = prices[0]#要找到卖股票的最低价
        
        for i in range(1,len(prices)):#从第二个价格开始遍历
            minprice = min(minprice,prices[i]) #比较当前价格和当前最低价哪个更小
            dp[i] = max(dp[i-1],prices[i] - minprice)
            #比较不卖或者卖出哪个可以获得更大的收益
        return dp[n-1]

122.买卖股票的最佳时机II

截图
这题其实可以不用动态规划去做。代码如下很简单。

def maxProfit(self, prices: List[int]) -> int:
        pro = 0 #可以获得总利润
        for i in range(1,len(prices)):
            tmp = prices[i] - prices[i-1]#每天都进行交易
            if tmp > 0:#如果是赚钱,则加到总利润中
                pro += tmp
        return pro

面试题08.01三步问题

dp

if n == 1:
            return 1
        elif n == 2:
            return 2
        elif n == 3:
            return 4
        tmp1,tmp2,tmp3 = 1,2,4
        for i in range(3,n):
            tmp1,tmp2,tmp3 = tmp2,tmp3,tmp1+tmp2+tmp3
            tmp1 = tmp1 % 1000000007
            tmp2 = tmp2 % 1000000007
            tmp3 = tmp3 % 1000000007
        return tmp3

70.爬楼梯

dp

dp ={
    
    }#dp矩阵
        dp[1]=1
        dp[2]=2
        for i in range(3,n+1):
            dp[i] = dp[i-1] + dp[i-2] #动态转移方程
        return dp[n]

很简单的一个动态规划的题目

746.使用最小路径爬楼梯

dp

n = len(cost)
        dp = [sys.maxsize] * (n+1) #初始化dp数组 dp【i】代表第i步的花费
        dp[0] = cost[0] #初始化
        dp[1] = cost[1] #初始化
        for i in range(2,n):
            dp[i] = min(dp[i-1],dp[i-2]) + cost[i] #转移方程
        return min(dp[n-1],dp[n-2])

343.整数拆分

dp

dp = [0] * (n+1) #初始化dp数组
        dp[2] = 1 #初始化dp[2]=1
        for i in range(3,n+1): #从第三个数开始赋值运算
            for j in range(1,i): #拆解i,从1一直到i-1
                dp[i] = max(dp[i],max(j * (i-j),j * dp[i-j]))
        return dp[-1]

62.不同路径

dp

def uniquePaths(self, m: int, n: int) -> int:
        #初始化二维矩阵,左边和右上都初始化为1
        dp = [[1] * n] + [[1] + [0] * (n-1) for _ in range(m-1)]
        for i in range(1,m):
            for j in range(1,n):
                dp[i][j] = dp[i-1][j] + dp[i][j-1]
        return dp[-1][-1]

63.不同路径II

dp

def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        row = len(obstacleGrid) #矩阵的行数
        column = len(obstacleGrid[0]) #矩阵的列数
        dp = [[0] * column for i in range(row)] #新建一个全是0的矩阵

        #下面是对矩阵的左边框和上边框赋值1 ,因为只有向右或者向下一种走法
        for i in range(row): 
            if obstacleGrid[i][0] == 1:#如果当前不是障碍物
                break
            dp[i][0] = 1
        for j in range(column):
            if obstacleGrid[0][j] == 1:#如果当前不是障碍物
                break
            dp[0][j] = 1
        
        for x in range(1,row): #从行开始循环
            for y in range(1,column): #从列开始循环
                if obstacleGrid[x][y] == 1: #遇到障碍物则退出
                    continue
                dp[x][y] = dp[x-1][y] + dp[x][y-1] #否则进行动态规划计算
        return dp[row-1][column-1]

猜你喜欢

转载自blog.csdn.net/weixin_38389509/article/details/113140002