DP-动态规划试题(Python实现)斐波那契、打家劫舍、股票买卖、背包、最长公共

目录

1. 斐波那契数列(1、1、2、3、5、8)

2. 青蛙跳台阶(1、2、3、5、8、13)

3. 青蛙跳台阶(进阶版)

4. 最小花费爬楼梯

5. 有多少个不同的二叉搜索树

6. 打家劫舍(一)

7. 打家劫舍(二)

8. 计算所需硬币最少个数

9. ​​​​​​​兑换零钱(一)

9. 买卖股票的最好时机(一)

10. 买卖股票的最好时机(二)

11. 买卖股票的最好时机(三)

12. 买卖股票的最佳时机 IV

13. 背包问题

14. ​​​​​​​把数字翻译成字符串

​​​​​​​15. 数字字符串转化成IP地址

16. ​​​​​​​正则表达式匹配

17. 最长公共子串

18. ​​​​​​​最长回文子串

19. ​​​​​​​最长的括号子串

20. 最长公共子序列(二)

21. ​​​​​​​最长上升子序列(一)

22. ​​​​​​​连续子数组的最大和


1. 斐波那契数列(1、1、2、3、5、8)

Fibonacci 前两数之和等于下一个数(前两个数都为1)

def fib(n):
    if n == 1 or n== 2:
        return 1
    a = 1
    b = 1
    for i in range(3, n+1):
        a, b = b, a+b    # tmp = b;    b = a + b;    a = tmp
    return b
########## 递 归 #########
def fib(n):
    if n == 1 or n == 2:
        return 1
    return fib(n-1) + fib(n-2)
########## DP动态规划 ##########
def fib(n):
    dp = [1]*(n+1)
    for i in range(3, n+1):
        dp[i] = dp[i-1] + dp[i-2]
    return dp[n]

2. 青蛙跳台阶(1、2、3、5、8、13)

def jumpFloor(n):
    a = 1
    b = 2
    if n == 1 or n== 2:
        return n
    for i in range(3, n+1):
        a, b = b, a+b    # tmp = b;    b = a + b;    a = tmp
    return b
########## 递 归 ##########
def jumpFloor(n):
    if n == 1 or n == 2:
        return n
    return fib(n-1) + fib(n-2)
########## DP动态规划 ##########
def jumpFloor(n):
    dp = [1]*(n+1)
    if n < 2:
        return dp[n]
    for i in range(2, n+1):
        dp[i] = dp[i-1] + dp[i-2]
    return dp[n]

3. 青蛙跳台阶(进阶版)

# 青蛙可以跳n级台阶
# 根据推导得,答案为 2的n-1次方
# return 2**(n-1)
def fib(n):
    ls = [0]*(n+1)
    if n==1 or n==2:
        return n
    ls[0], ls[1], ls[2] = 1, 1, 2
    for i in range(3,n+1):
        for j in range(i):
            ls[i] += ls[j]
    return ls[-1]

4. 最小花费爬楼梯

核心思想:目的楼层的最小花费 = min(前一台阶到此的花费前两台阶到此的花费)

class Solution:
    def minCostClimbingStairs(self , cost: List[int]) -> int:
        # dp[i] 表示爬到第i阶梯需要的最小花费
        n = len(cost)
        dp = [0 for i in range(n+1)]    # [0]*(n+1)
        for i in range(2, n+1):
            dp[i] = min(dp[i-2] + cost[i-2], dp[i-1] + cost[i-1])
        return dp[-1]

5. 有多少个不同的二叉搜索树

# 以j为头结点进行搜索,左子树有j-1个节点,右子树有i-j个节点
# 状态转移方程:i个节点的树个数=j个节点左子树个数*i-1-j个节点右子树个数
n = int(input())
dp = [0]*(n+1)
dp[0],dp[1] = 1,1
for i in range(2,n+1):
    for j in range(i):
        dp[i] += dp[j]*dp[i-j-1]
print(dp[n])

6. ​​​​​​​打家劫舍(一)

class Solution:
    def rob(self, nums: List[int]) -> int:
        # dp[i]表示长度为i的数组,最多能偷取多少钱
        dp = [0 for i in range(len(nums) + 1)]
        # 长度为1只能偷第一家
        dp[1] = nums[0]
        for i in range(2, len(nums) + 1):
            # 对于每家可以选择偷或者不偷
            dp[i] = max(dp[i - 1], nums[i - 1] + dp[i - 2])
        return dp[len(nums)]

7. 打家劫舍(二)

class Solution:
    def rob(self, nums: List[int]) -> int:
        # dp[i]表示长度为i的数组,最多能偷取多少钱
        dp1 = [0 for i in range(len(nums) + 1)]
        # 选择偷了第一家
        dp1[1] = nums[0]
        # 最后一家不能偷
        for i in range(2, len(nums)):
            # 对于每家可以选择偷或者不偷
            dp1[i] = max(dp1[i - 1], nums[i - 1] + dp1[i - 2])
        res = dp1[len(nums) - 1]
        # 第二次循环
        dp2 = [0 for i in range(len(nums) + 1)]
        # 不偷第一家
        dp2[1] = 0
        # 可以偷最后一家
        for i in range(2, len(nums) + 1):
            # 对于每家可以选择偷或者不偷
            dp2[i] = max(dp2[i - 1], nums[i - 1] + dp2[i - 2])
            # 选择最大值
        return max(res, dp2[len(nums)])

8. 计算所需硬币最少个数

class Solution:
    def calculationCoin(self, coins: List[int], amount: int) -> int:
        # 初始化dp
        dp = [amount + 1] * (amount + 1)
        # 目标金额为 0 时,硬币数量为 0 
        dp[0] = 0

        for i in range(1, amount + 1): 
            for coin in coins: 
                if coin <= i: 
                    dp[i] = min(dp[i], dp[i - coin] + 1) 
        return -1 if dp[amount] > amount else dp[amount]

9. ​​​​​​​兑换零钱(一)

class Solution:
    def minMoney(self, arr: List[int], aim: int) -> int:
        # 小于1的都返回0
        if aim < 1:
            return 0
        # dp[i]表示凑齐i元最少需要多少货币数
        dp = [(aim + 1) for i in range(aim + 1)]
        dp[0] = 0
        # 遍历1-aim元
        for i in range(1, aim + 1):
            # 每种面值的货币都要枚举
            for j in range(len(arr)):
                # 如果面值不超过要凑的钱才能用
                if arr[j] <= i:
                    # 维护最小值
                    dp[i] = min(dp[i], dp[i - arr[j]] + 1)
        # 如果最终答案大于aim代表无解
        if dp[aim] > aim:
            return -1
        else:
            return dp[aim]

9. 买卖股票的最好时机(一)

暴力法:

class Solution:
    def maxProfit(self , prices: List[int]) -> int:
        res = 0
        for i in range(len(prices)):
            for j in range(i+1, len(prices)):
                res = max(res, prices[j] - prices[i])
        return res

一次遍历:minprice记录股票最低价格,maxprofit记录最大利润

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        minprice = int(1e9)
        maxprofit = 0
        for price in prices:
            maxprofit = max(price - minprice, maxprofit)
            minprice = min(price, minprice)
        return maxprofit

dp动态规划:

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        n = len(prices)
        if n == 0: return 0
        # j=0表示不持股,j=1表示持股
        # dp[i][0]表示某一天不持股到该天为止的最大收益
        # dp[i][1]表示某天持股,到该天为止的最大收益

        dp = [[0] * 2 for i in range(n)]
        # 第一天不持股,总收益为0
        dp[0][0] = 0
        # 第一天持股,总收益为减去该天的股价
        dp[0][1] = -prices[0]
        # 遍历后续每天,状态转移
        for i in range(1, n):
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i])
            dp[i][1] = max(dp[i - 1][1], -prices[i])
        # 最后一天不持股,到该天为止的最大收益
        return dp[n - 1][0]

一维dp动态规划最优版:​​​​​​​

class Solution:
    def maxProfit(self , prices: List[int]) -> int:
        n = len(prices)
        if n == 0: return 0
        dp = [0]*n
        minprice = prices[0]
        for i in range(1,n):
            minprice = min(minprice, prices[i])
            dp[i] = max(dp[i-1], prices[i] - minprice)
        return dp[-1]

10. 买卖股票的最好时机(二)

暴力法:

class Solution:
    def maxProfit(self , prices: List[int]) -> int:
        res = 0
        n = len(prices)
        for i in range(n-1):
            diff = prices[i+1] - prices[i]
            if diff > 0:
                res += diff
        return res

dp动态规划:

class Solution:
    def maxProfit(self , prices: List[int]) -> int:
        n = len(prices)
        if n <= 1: return 0
        # cash为当天持有现金(不持股)的最大收益
        # hold为当天持有股票的最大收益
        cash = [0]*n
        hold = [0]*n
        # 第一天不持股,收益为0
        cash[0] = 0
        # 第一天持股,收益为-该天的股价
        hold[0] = -prices[0]
        for i in range(1, n):
            cash[i] = max(cash[i-1], hold[i-1] + prices[i])
            hold[i] = max(hold[i-1], cash[i-1] - prices[i])
        return cash[-1]

# 另一种形式
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        n = len(prices)
        # 0为不持股,1为持股
        # dp[i][0]表示某一天不持股到该天为止的最大收益
        # dp[i][1]表示某天持股,到该天为止的最大收益
        
        dp = [[0, 0] for i in range(n)]
        # 第一天不持股,总收益为0
        dp[0][0] = 0
        # 第一天持股,总收益为减去该天的股价
        dp[0][1] = -prices[0]
        # 遍历后续每天,状态转移
        for i in range(1, n):
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i])
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i])
        # 最后一天不持股,到该天为止的最大收益
        return dp[n - 1][0]

变量记录(dp动态规划最优版):

class Solution:
    def maxProfit(self , prices: List[int]) -> int:
        n = len(prices)
        if n <= 1: return 0
        cash = 0
        hold = -prices[0]
        preCash = cash
        preHold = hold
        for i in range(1, n):
            cash = max(preCash, preHold + prices[i])
            hold = max(preHold, preCash - prices[i])
            preCash = cash
            preHold = hold
        return cash

11. 买卖股票的最好时机(三)

class Solution:
    def maxProfit(self , prices: List[int]) -> int:
        n = len(prices)
        if n <= 1: return 0
        # dp[i][j]表示i时间下,j=0为没操作,1为第一次买入一支股票,2为第一次卖出一支股票,3为第2次买入一支股票,4为第2次卖出一支股票
        dp = [[int(-1e9)]*5 for i in range(n)]
        # 第一天不操作
        dp[0][0] = 0
        # 第一天第一次买入
        dp[0][1] = -prices[0]
        for i in range(1, n):
            dp[i][0] = 0
            dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
            dp[i][2] = max(dp[i-1][2], dp[i-1][1] + prices[i])
            dp[i][3] = max(dp[i-1][3], dp[i-1][2] - prices[i])
            dp[i][4] = max(dp[i-1][4], dp[i-1][3] + prices[i])
        # max(没操作,一次卖出,两次卖出)
        return max(0, max(dp[-1][2], dp[-1][4]))

变量记录(dp动态规划最优版):

class Solution:
    def maxProfit(self , prices: List[int]) -> int:
        n = len(prices)
        if n <= 1: return 0
        dp = [0 for _ in range(5)]
        # 0没操作,1第一次买入,2第一次卖出,3第二次买入,4第二次卖出
        dp[0] = 0
        dp[1] = -prices[0]
        dp[3] = int(-1e9)

        for i in range(1, n):
            dp[0] = 0
            dp[1] = max(dp[1], -prices[i])
            dp[2] = max(dp[2], dp[1] + prices[i])
            dp[3] = max(dp[3], dp[2] - prices[i])
            dp[4] = max(dp[4], dp[3] + prices[i])
        return max(0 ,max(dp[2], dp[4]))

12. 买卖股票的最佳时机 IV

三维dp:

class Solution:
    def maxProfit(self, k: int, prices: List[int]) -> int:
        n = len(prices)
        if n <= 1: return 0
        # 若k大于数组的一半,即可以无限次交易
        if k > n//2:
            cash = 0
            hold = -prices[0]
            preCash = cash
            preHold = hold
            for i in range(1, n):
                cash = max(preCash, preHold + prices[i])
                hold = max(preHold, preCash - prices[i])
                preCash = cash
                preHold = hold
            return cash
        # 三维dp,第i天,交易了多少次,当前的买卖状态(0为卖出,1为买入)
        dp = [[[0,0] for i in range(k+1)] for _ in range(n)]
        # 初始化第一天
        for i in range(k+1):
            dp[0][i][0] = 0
            dp[0][i][1] = -prices[0]
        for i in range(1, n):
            for j in range(1, k+1):
                # 处理第k次买入
                dp[i][j-1][1] = max(dp[i-1][j-1][1], dp[i-1][j-1][0] - prices[i])
                # 处理第k次卖出
                dp[i][j][0] = max(dp[i-1][j][0], dp[i-1][j-1][1] + prices[i])
        return dp[-1][k][0]

二维dp:

class Solution:
    def maxProfit(self, k: int, prices: List[int]) -> int:
        n = len(prices)
        if n <= 1: return 0
        # 若k大于数组的一半,即可以无限次交易
        if k > n//2:
            cash = 0
            hold = -prices[0]
            preCash = cash
            preHold = hold
            for i in range(1, n):
                cash = max(preCash, preHold + prices[i])
                hold = max(preHold, preCash - prices[i])
                preCash = cash
                preHold = hold
            return cash
        # 二维dp,交易了多少次,当前的买卖状态(0为卖出,1为买入)
        dp = [[0,0] for _ in range(k+1)]
        for i in range(k+1):
            dp[i][1] = -prices[0]
        for i in range(1, n):
            for j in range(k, 0, -1):
                # 处理第k次买入
                dp[j-1][1] = max(dp[j-1][1], dp[j-1][0] - prices[i])
                # 处理第k次卖出
                dp[j][0] = max(dp[j][0], dp[j-1][1] + prices[i])
        return dp[-1][0]

13. 背包问题

# 背包所能容纳的最大价值
n,v = map(int,input().split())
dp = [[0 for i in range(v+1)] for j in range(n+1)]
lv, lw = [], []
for i in range(n):
    l = (list(map(int,input().split())))
    lv.append(l[0])    # 物品重量列表
    lw.append(l[1])    # 物品价值列表

# 👇核心代码👇
for i in range(1,n+1):
    for j in range(1,v+1):
        if j < lv[i-1]:
            dp[i][j] = dp[i-1][j]
        else:
            dp[i][j] = max(dp[i-1][j],dp[i-1][j-lv[i-1]]+lw[i-1])
print(dp[n][v])

01背包:​​​​​​​共有n个物品,给定一个容量为V的背包。接下来n行,每行有该物品的体积和价值。

  1. 求背包能装的最大价值。
  2. 如果背包恰好装满,最多能装多大价值的物品。
import sys
n,v = map(int,input().split())
lv, lw = [0], [0]
for i in range(n):
    l = (list(map(int,input().split())))
    lv.append(l[0])    # 物品重量列表
    lw.append(l[1])    # 物品价值列表

# dp1为第一题,不考虑背包是否装满,最多装多大价值的物品
dp1 = [0 for i in range(v+1)]
# dp2为第二题,在背包恰好装满时,最多装多大价值的物品
dp2 = [-sys.maxsize-1 for i in range(v+1)]
dp2[0] = 0
for i in range(1,n+1):
    for j in range(v, lv[i]-1, -1):
        dp1[j] = max(dp1[j],dp1[j-lv[i]]+lw[i])
        dp2[j] = max(dp2[j],dp2[j-lv[i]]+lw[i])
print(dp1[v])
print(0) if dp2[v]<0 else print(dp2[v])

14. ​​​​​​​把数字翻译成字符串

class Solution:
    def solve(self, nums: str) -> int:
        # 排除0
        if nums == "0":
            return 0
        # 排除只有一种可能的10 和 20
        if nums == "10" or nums == "20":
            return 1
        # 当0的前面不是1或2时,无法译码,0种
        for i in range(1, len(nums)):
            if nums[i] == "0":
                if nums[i - 1] != "1" and nums[i - 1] != "2":
                    return 0
        # 辅助数组初始化为1
        dp = [1 for i in range(len(nums) + 1)]
        for i in range(2, len(nums) + 1):
            # 在11-19,21-26之间的情况
            if (nums[i - 2] == "1" and nums[i - 1] != "0") or (
                nums[i - 2] == "2" and nums[i - 1] > "0" and nums[i - 1] < "7"):
                dp[i] = dp[i - 1] + dp[i - 2]
            else:
                dp[i] = dp[i - 1]
        return dp[len(nums)]

​​​​​​​15. 数字字符串转化成IP地址

class Solution:
    def __init__(self):
        self.res = []
        self.s = ""
        self.nums = ""

    # step表示第几个数字,index表示字符串下标
    def dfs(self, step: int, index: int):
        # 当前分割出的字符串
        cur = ""
        # 分割出了四个数字
        if step == 4:
            # 下标必须走到末尾
            if index != len(self.s):
                return
            self.res.append(self.nums)
        else:
            i = index
            # 最长遍历3位
            while i < index + 3 and i < len(self.s):
                cur += self.s[i]
                # 转数字比较
                num = int(cur)
                temp = self.nums
                # 不能超过255且不能有前导0
                if num <= 255 and (len(cur) == 1 or cur[0] != "0"):
                    # 添加点
                    if step - 3 != 0:
                        self.nums += cur + "."
                    else:
                        self.nums += cur
                    # 递归查找下一个数字
                    self.dfs(step + 1, i + 1)
                    # 回溯
                    self.nums = temp
                i += 1

    def restoreIpAddresses(self, s: str) -> List[str]:
        self.s = s
        self.dfs(0, 0)
        return self.res

16. ​​​​​​​正则表达式匹配

class Solution:
    def match(self, str: str, pattern: str) -> bool:
        n1 = len(str)
        n2 = len(pattern)
        # dp[i][j]表示str前i个字符和pattern前j个字符是否匹配
        dp = [[False] * (n2 + 1) for i in range(n1 + 1)]
        # 两个都为空串自然匹配
        dp[0][0] = True
        # 初始化str为空的情况,字符串下标从1开始
        for i in range(2, n2 + 1):
            # 可以让自己前面个字符重复0次
            if pattern[i - 1] == "*":
                # 与再前一个能够匹配空串有关
                dp[0][i] = dp[0][i - 2]
        # 遍历str每个长度
        for i in range(1, n1 + 1):
            # 遍历pattern每个长度
            for j in range(n2 + 1):
                # 当前字符不为*,用.去匹配或者字符直接相同
                if pattern[j - 1] != "*" and (
                    pattern[j - 1] == "." or pattern[j - 1] == str[i - 1]
                ):
                    dp[i][j] = dp[i - 1][j - 1]
                # 当前的字符为*
                elif j >= 2 and pattern[j - 1] == "*":
                    # 若是前一位为.或者前一位可以与这个数字匹配
                    if pattern[j - 2] == "." or pattern[j - 2] == str[i - 1]:
                        # 转移情况
                        dp[i][j] = dp[i - 1][j] or dp[i][j - 2]
                    else:
                        # 不匹配
                        dp[i][j] = dp[i][j - 2]
        return dp[n1][n2]

17. 最长公共子串

class Solution:
    def LCS(self , str1: str, str2: str) -> str:
        # 让str1为较长的字符串
        if len(str1) < len(str2):
            str1 ,str2 = str2, str1
        res = ""
        length = 0
        for i in range(len(str1)):
            if str1[i-length : i+1] in str2:
                res = str1[i-length: i+1]
                length += 1
        return res

18. ​​​​​​​最长回文子串

暴力法:

class Solution:
    # 验证是否是回文
    def Valid(self, s: str, l: int, r: int) -> bool:
        while l < r:
            if s[l] != s[r]:
                return False
            l += 1
            r -= 1
        return True
    def getLongestPalindrome(self , A: str) -> int:
        # 记录最长回文子串的长度
        maxlen = 1
        # 记录最长回文子串的起始点
        begin = 0
        for i in range(len(A)-1):
            for j in range(len(A)-1, i, -1):
                if j-i+1 > maxlen and self.Valid(A, i, j):
                    maxlen = j-i+1
                    begin = i
                    break
        # 最长回文子串为:A[begin:begin+maxlen]
        return maxlen

中心扩散法:

class Solution:
    # 中心扩散
    def fun(self, s: str, begin: int, end: int) -> int:
        # 每个中心点开始扩散
        while begin >= 0 and end <= len(s)-1 and s[begin] == s[end]:
            begin -= 1
            end += 1
        # 返回长度
        return end - begin - 1
    def getLongestPalindrome(self , A: str) -> int:
        maxlen = 1
        # 以每个点为中心
        for i in range(len(A) - 1):
            # 分奇数长度 和 偶数长度向两边扩展
            maxlen = max(maxlen, max(self.fun(A, i, i), self.fun(A, i, i+1)))
        return maxlen
———————— E N D ———————— E N D ———————— E N D ————————
    # 若获取最长子串的方法
    def getLongestPalindrome(self , A: str) -> int:
        maxlen = 1
        begin = 0
        # 以每个点为中心
        for i in range(len(A) - 1):
            max_now = max(self.fun(A, i, i), self.fun(A, i, i+1))
            if maxlen < max_now:
                maxlen = max_now
                begin = i - (maxlen-1)//2
        return A[begin:begin+maxlen]

19. ​​​​​​​最长的括号子串

class Solution:
    def longestValidParentheses(self, s: str) -> int:
        res = 0
        # 记录上一次连续括号结束的位置
        start = -1
        st = []
        for i in range(len(s)):
            # 左括号入栈
            if s[i] == "(":
                st.append(i)
            # 右括号
            else:
                # 如果右括号时栈为空,不合法,设置为结束位置
                if len(st) == 0:
                    start = i
                else:
                    # 弹出左括号
                    st.pop()
                    # 栈中还有左括号,说明右括号不够,减去栈顶位置就是长度
                    if len(st) != 0:
                        res = max(res, i - st[-1])
                    # 栈中没有括号,说明左右括号行号,减去上一次结束的位置就是长度
                    else:
                        res = max(res, i - start)
        return res

20. 最长公共子序列(二)

class Solution:
    def __init__(self):
        self.x = ""
        self.y = ""
    #获取最长公共子序列
    def ans(self, i: int, j: int, b: List[List[int]]):
        res = ""
        #递归终止条件
        if i == 0 or j == 0:
            return res
        #根据方向,往前递归,然后添加本级字符
        if b[i][j] == 1:
            res = res + self.ans(i - 1, j - 1, b)
            res = res + self.x[i - 1]
        elif b[i][j] == 2:
            res = res + self.ans(i - 1, j, b)
        elif b[i][j] == 3:
            res = res + self.ans(i, j - 1, b)
        return res
    def LCS(self , s1: str, s2: str) -> str:
        #特殊情况
        if s1 is None or s2 is None:
            return "-1"
        len1 = len(s1)
        len2 = len(s2)
        self.x = s1
        self.y = s2
        #dp[i][j]表示第一个字符串到第i位,第二个字符串到第j位为止的最长公共子序列长度
        dp = [[0] * (len2 + 1) for i in range(len1 + 1)]
        #动态规划数组相加的方向
        b = [[0] * (len2 + 1) for i in range(len1 + 1)]
        #遍历两个字符串每个位置求的最长长度
        for i in range(1, len1 + 1):
            for j in range(1, len2 + 1):
                #遇到两个字符相等
                if s1[i - 1] == s2[j - 1]:
                    #考虑由二者都向前一位
                    dp[i][j] = dp[i - 1][j - 1] + 1
                    #来自于左上方
                    b[i][j] = 1
                #遇到的两个字符不同
                #左边的选择更大,即第一个字符串后退一位
                elif dp[i - 1][j] > dp[i][j - 1]:
                    dp[i][j] = dp[i - 1][j]
                    #来自于左方
                    b[i][j] = 2
                #右边的选择更大,即第二个字符串后退一位
                else:
                    dp[i][j] = dp[i][j - 1]
                    #来自于上方
                    b[i][j] = 3
        #获取答案字符串
        res = self.ans(len1, len2, b)
        #检查答案是否位空
        if res is None or res == "":
            return "-1"
        else:
            return res

21. ​​​​​​​最长上升子序列(一)

class Solution:
    def LIS(self, arr: List[int]) -> int:
        # 设置数组长度大小的动态规划辅助数组
        dp = [1 for i in range(len(arr))]
        res = 0
        for i in range(1, len(arr)):
            for j in range(i):
                # 可能j不是所需要的最大的,因此需要dp[i] < dp[j] + 1
                if arr[i] > arr[j] and dp[i] < dp[j] + 1:
                    # i点比j点大,理论上dp要加1
                    dp[i] = dp[j] + 1
                    # 找到最大长度
                    res = max(res, dp[i])
        return res

22. ​​​​​​​连续子数组的最大和

class Solution:
    def FindGreatestSumOfSubArray(self, array: List[int]) -> int:
        # 记录到下标i为止的最大连续子数组和
        dp = [0 for i in range(len(array))]
        dp[0] = array[0]
        maxsum = dp[0]
        for i in range(1, len(array)):
            # 状态转移:连续子数组和最大值
            dp[i] = max(dp[i - 1] + array[i], array[i])
            # 维护最大值
            maxsum = max(maxsum, dp[i])
        return maxsum

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值