《极客时间--算法面试》--动态规划
题目:70、爬楼梯
思路:
一、采用回溯法,递归+记忆化
二、采用动态规划,时间复杂度为O(n),采用递推的方式
要找到DP的状态和DP方程。
代码(动态规划):
class Solution(object): def climbStairs(self, n): """ :type n: int :rtype: int """ ''' 方式一:传统的方式 if n==0 or n==1 or n==2: #边界值判定 return n men = [1,2] #递推初始值 for i in range(2,n): #从第二个开始到最后 men.append(men[i-1]+men[i-2]) #将前面两个值相加最为后一个值 return men[n-1] #返回最后的一个结果 ''' '''方式二:python的编码方式较为简洁,直接赋值的''' x,y = 1,1 for _ in range(1,n): x,y = y,x+y return y
题目:120、三角形最小路径和
思路:
一、回溯
二、动态规划
从底层倒推,明确状态转移方程和初始状态。
初始状态是最后一层,转移方程是相邻节点的最小值和当前值相加作为下一个状态的值。
代码:
class Solution(object): def minimumTotal(self, triangle): """ :type triangle: List[List[int]] :rtype: int """ if not triangle: #边界判断 return 0 res = triangle[-1] #初始状态为最后层 for i in range(len(triangle)-2,-1,-1): #从底层到上层进行遍历 for j in range(len(triangle[i])): #每一层从左往右遍历 res[j] = min(res[j],res[j+1])+triangle[i][j] #当前节点的相邻节点之间最小值加上当前节点 return res[0] #最终的结果值就是最顶层的数
需要一个一维的数组进行状态压缩。
题目:152乘积最大子序列
思路:
一、采用递归的思路,暴力解决
采用递归的思路但采用循环的方式编码。对每一个值进行乘积,将当前最大值进行保存起来,如果与当前的乘积小于前面值就赋值为1.最终返回最大的那个值即可。
二、采用动态规划,采用递推的方式
一、状态的定义,一个二维方程,存放正向最大值和负向最小值,两个负数相乘会变正数。
二、状态方程,最大和最小的值,是比较当前值和当前值和前面乘积的乘积。
代码:
class Solution(object): def maxProduct(self, nums): """ :type nums: List[int] :rtype: int """ if nums is None: return 0 #边界判断 dp = [[0 for _ in range(2)]for _ in range(2)] #定义状态,二维数组,存放正向最大和负向最小 dp[0][1],dp[0][0],res = nums[0],nums[0],nums[0] #状态初始值,从第一个值开始 for i in range(1,len(nums)): #从第二个值开始遍历 x,y = i%2,(i-1)%2 #0,1周期性调控 dp[x][0] = max(dp[y][0]*nums[i],dp[y][1]*nums[i],nums[i]) #正向最大值 dp[x][1] = min(dp[y][0]*nums[i],dp[y][1]*nums[i],nums[i]) #负向最小值 res = max(res,dp[x][0]) #每次都保存最大的值,最终返回 return res
以下题目买卖股票的最佳时机系列题目均采用动态规划思路去做,明确动态规划的两个基本点:定义状态、状态转移方程和最终的目标结果值。以下思路是通用的泛华思路,定义了三个状态,根据具体的需求再进行细微修改。
明确状态含义:
dp[i][j][k]:第i天的最大收益第k次交易的最大收益
i:第i天【0,n-1】
j:手上是否持有【0、1】代表手上只能持有一股,可以多股
k:第k次交易【0,k】
如果是冷冻时期可以在加状态,比如是否冷冻期,取值范围是0、1等。
初始状态:
状态转义方程:
通俗讲:在考虑上次交易的前提下,根据手上是否有股票分别作出行动,由于只有两种情况,即是否持有,后期可以改为
手上有股票:保持当前的股票和卖掉手上的股票的最大值
手上没有股票:保持手上没有股票和买入当前饿股票的最大值
三个循环进行遍历,第一个循环遍历第几天,第二个循环遍历第几次买卖。第三个循环根据手上的股票个数进行操作。针对第一题只有一个股票,后面多个股票,细微修改。
最终的结果值是最后一天股票操作后在这k次中最大的一个利润值。
股票买卖题目:121股票买卖的最佳时机I
只能进行一次交易
思路:
代码:
股票买卖题目:122股票买卖的最佳时机II
无数次交易
思路:
代码:
股票买卖题目:123股票买卖的最佳时机III
只能两次交易
思路:
代码:
股票买卖题目:188股票买卖的最佳时机IV
K次交易
思路:
代码:
股票买卖题目:309最佳股票买卖的最佳时机含冷冻期
两次交易中间会有限制
思路:
代码:
股票买卖题目:714股票买卖的最佳时机含手续费
思路:
代码: