美文网首页
07-03:动态规划review1

07-03:动态规划review1

作者: 是黄小胖呀 | 来源:发表于2021-07-03 23:35 被阅读0次

1、最大连续子数组和

    关键核心是累加和的正负:

2、零钱组合

1)最少硬币数

总钱数:总硬币数:动态规划迭代:

外部总硬币数:

内部总钱数:

自底向上迭代:

核心代码如下:
dp = [float('inf')] * (amount + 1)

        dp[0] = 0

        for coin in coins:

            for j in range(coin,amount+1):

                  dp[j] = min(dp[j], dp[j - coin] + 1)

        return dp[amount] if dp[amount] != float('inf') else -1

零钱组合1

2)满足钱数的多少种组合数

外部总硬币数:

内部总钱数:

自底向上累加:

核心思路:

对于面额为coin 的硬币,当 coin≤i≤amount 时,如果存在一种硬币组合的金额之和等于 i −coin,则在该硬币组合中增加一个面额为 coin 的硬币,即可得到一种金额之和等于 i的硬币组合。因此需要遍历 coins,对于其中的每一种面额的硬币,更新数组 dp 中的每个大于或等于该面额的元素的值。

核心代码如下:

n=len(coins)

        if amount==0 or n==0:

            return 1

        dp=[0]*(amount+1)

        dp[0]=1

        for coin in coins:

            for j in range(coin,amount+1):

                dp[j]=dp[j]+dp[j-coin]

        return dp[amount]

3)组合总数

leetcode377

给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。

https://leetcode-cn.com/problems/combination-sum-iv/

dp=[0]*(target + 1)

        dp[0] = 1

        for  i in range(1,target+1):

            for  num  in nums:

                  if num <= i:

                    dp[i] += dp[i - num]

        return dp[target]

3、01背包

总体积:总物品数:动态规划迭代:体积V

核心问题:

自顶向下不断递归迭代

核心代码:

if V<=0 or n<=0:

            return 0

        dp=[0 for i in range(V+1)]

        for i in range(n):

            vi=vw[i][0]

            wi=vw[i][1]

            for j in range(V,vi-1,-1):

                dp[j]=max(dp[j-vi]+wi,dp[j])

        return dp[V]

牛客网01背包问题:
https://www.nowcoder.com/practice/2820ea076d144b30806e72de5e5d4bbf?tpId=196&&tqId=37561&rp=1&ru=/activity/oj&qru=/ta/job-code-total/question-ranking

1)完全平方数

核心代码如下:

k=int(sqrt(n))

        dp=[float('inf')]*(n+1)

        dp[0]=0

        dp[1]=1

        for i in range(1,k+1):

            tmp=i*i

            for j in range(tmp,n+1):

                dp[j]=min(dp[j],dp[j-tmp]+1)

        return dp[n]

2)掷骰子的N种方法

leetcode1155

投掷骰子的方法数:d个骰子,每个有f个面(点数为1,2,...f),求骰子点数和为target的方法

分组0/1背包的组合问题:dp[i][j]表示投掷i个骰子点数和为j的方法数;三层循环:最外层为背包d,然后先遍历target后遍历点数f

应用二维拓展的转移方程3:dp[i][j]+=dp[i-1][j-f];

链接:https://leetcode-cn.com/problems/coin-change/solution/yi-pian-wen-zhang-chi-tou-bei-bao-wen-ti-sq9n/

3)最长递增子序列 leetcode300

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

1、贪心+二分查找

贪心:保持数组递增

二分查找:查找不满足大于数组最大值的位置,第一个小于原数组中元素

时间复杂度:o(nlogn)

空间复杂度:o(n)

核心代码:

n=len(nums)

        l=[]

        length=0

        if n<=1:

            return len(nums)

        l.append(nums[0])

        for i in range(1,n):

            if  nums[i]>l[-1]:

                      l.append(nums[i])

            else:

                #在数组中二分查找,找到第一个比 nums[i] 小的数,并更新 d[k + 1] = nums[i]。

                k=len(l)

                left=0

                right=k-1

                while left<=right:

                    mid=(left+right)//2

                    if l[mid]<nums[i]:

                        left=mid+1

                    else:

                        right=mid-1

                l[left]=nums[i]

        return len(l)

调用函数代码简单:

import bisect

class Solution:

    def lengthOfLIS(self, nums: List[int]) -> int:

        n=len(nums)

        ls=[]

        if n<=1:

            return len(nums)

        dp=[1 for i in range(n)]

        ls.append(nums[0])

        for i in range(n):

                if nums[i]>ls[-1]:

                  ls.append(nums[i])

                else:

                    tmp=bisect.bisect_left(ls,nums[i])

                    ls[tmp]=nums[i]

        return len(ls)

2、动态规划

包含当前数组元素的上升子序列最大值,状态转移:dp[i]=max(dp[i],dp[i-j]+1),nums[i]>nums[j]

核心代码:

n=len(nums)

        l=[]

        if n<=1:

            return len(nums)

        dp=[1 for i in range(n)]

        for i in range(n):

            for j in range(i):

                if nums[i]>nums[j]:

                  dp[i]=max(dp[i],dp[j]+1)

        return max(dp)

https://leetcode-cn.com/problems/longest-increasing-subsequence/

3、字典序最长上升子序列

一共需要两个辅助数组和一个辅助变量:

dp数组:用来存储位置i对应的最长子序列的长度

end数组:用来存储长度为i的子序列的最后一个元素的最小值

len:用来记录当前找到的最长子序列的长度

最后产生字典序最小的:

核心代码如下:

import bisect

#bisect.bisect_left(ls,arr[i]),返回第一个小于arr[i]的索引

def LIS(self , arr ):

        # write code here

        if not arr:

            return 0

        n=len(arr)

        dp = [1 for i in range(n)]

        ls=[arr[0]]

        res=[]

        for i in range(1,n):

                  if arr[i] > ls[-1]:

                        ls.append(arr[i])

                        dp[i]=len(ls)

                  else:

                        tmp=bisect.bisect_left(ls,arr[i])

                        ls[tmp]=arr[i]

                        dp[i]=tmp+1

        lls=len(ls)

        res=[0]*lls

        for i in range(n-1,-1,-1):

            if dp[i]==lls:

                res[lls-1]=arr[i]

                lls=lls-1

        return res

https://www.nowcoder.com/practice/9cf027bf54714ad889d4f30ff0ae5481?tpId=117&&tqId=37796&rp=1&ru=/activity/oj&qru=/ta/job-code-high/question-ranking

4)最长回文串长度

动态规划节最长回文子串长度:

核心代码如下:

dp=[[False]*n for i in range(n)]

            smax=0

            for d in range(n):

                for i in range(n-d):

                    j=i+d

                    if A[i]==A[j]:

                        if d==0 or d==1 or d==2:

                            dp[i][j]=True

                        else:

                            dp[i][j]=dp[i+1][j-1]

                        if dp[i][j]:

                            smax=max(smax,d+1)

            return  smax

5)股票交易(两次)

1、初始5个状态

2、状态转移

什么都不做,和前一天买入/卖出最大收益+当前操作

核心代码:

dp0[0]=0

        dp1[0]=-prices[0]

        dp2[0]=0

        dp3[0]=-prices[0]

        dp4[0]=0

        for i in range(1,k):

            dp0[i]=dp0[i-1]

            dp1[i]=max(dp1[i-1],dp0[i-1]-prices[i])

            dp2[i]=max(dp2[i-1],dp1[i-1]+prices[i])

            dp3[i]=max(dp3[i-1],dp2[i-1]-prices[i])

            dp4[i]=max(dp4[i-1],dp3[i-1]+prices[i])

        return dp4[k-1]

动态规划总结:

https://leetcode-cn.com/problems/coin-change/solution/yi-pian-wen-zhang-chi-tou-bei-bao-wen-ti-sq9n/

相关文章

  • 07-03:动态规划review1

    1、最大连续子数组和 关键核心是累加和的正负: 2、零钱组合 1)最少硬币数 总钱数:总硬币数:动态规划迭代:...

  • Algorithm进阶计划 -- 动态规划(上)

    动态规划动态规划的基本原理动态规划的运用 1. 动态规划的基本原理 动态规划(Dynamic Programmi...

  • 4. 动态规划算法

    1. 动态规划算法总结2. 漫画:什么是动态规划?3.算法之动态规划4. 动态规划-算法

  • 动态规划 Dynamic Programming

    从运筹学和算法的角度综合介绍动态规划 算法分类总结动态规划与静态规划的关系浅析静态规划和动态规划动态规划解非线性规...

  • 《数据结构与算法之美》27——初识动态规划

    前言 今天开始学习动态规划,一共有三节,分别是:初识动态规划、动态规划理论、动态规划实战。今天这一节就是初识动态规...

  • 算法3:动态规划

    5.动态规划5.1 什么是动态规划?5.2 自底向上的动态规划:5.3 自顶向下的动态规划5.4 0-1背包问题:...

  • 动态规划

    动态规划(Dynamic Programming) 本文包括: 动态规划定义 状态转移方程 动态规划算法步骤 最长...

  • Dynamic Programming(动态规划)类算法分析随笔

    #动态规划 关于动态规划,先摘一段[wiki][1]的描述: ``` 动态规划(英语:Dynamic progra...

  • 什么是动态规划

    目录 动态规划解决了什么 什么是动态规划 典型的动态规划 1. 动态规划解决了什么 的思想就是将大问题拆分成小问题...

  • 斐波那契数列

    递归解法 动态规划解法1 动态规划解法2

网友评论

      本文标题:07-03:动态规划review1

      本文链接:https://www.haomeiwen.com/subject/shzpultx.html