• 动态规划


    难度简单

    给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

    示例:

    输入: [-2,1,-3,4,-1,2,1,-5,4],
    输出: 6
    解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
    

    进阶:

    如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。

     1 class Solution:
     2     def maxSubArray(self, nums: List[int]) -> int:
     3         nums_len = len(nums)
     4         if nums_len == 1:
     5             return nums[0]
     6         #dp[i]代表着以nums[i]为结尾的最大和的连续子数组
     7         #dp[i] = max(dp[i-1]+nums[i], nums[i])
     8         dp = deepcopy(nums)
     9         for i in range(1, nums_len):
    10             dp[i] = max(dp[i-1]+nums[i], nums[i])
    11 
    12         return max(dp)

    70. 爬楼梯

    难度简单

    假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

    每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

    注意:给定 n 是一个正整数。

    示例 1:

    输入: 2
    输出: 2
    解释: 有两种方法可以爬到楼顶。
    1.  1 阶 + 1 阶
    2.  2 阶

    示例 2:

    输入: 3
    输出: 3
    解释: 有三种方法可以爬到楼顶。
    1.  1 阶 + 1 阶 + 1 阶
    2.  1 阶 + 2 阶
    3.  2 阶 + 1 阶
     1 class Solution:
     2     def climbStairs(self, n: int) -> int:
     3         #dp[i]代表当有i阶楼梯时有多少种方法可以到达楼顶
     4         #dp[i] = dp[i-1] + dp[i-2]
     5         dp = [1 for _ in range(n+1)]
     6 
     7         for i in range(2, n+1):
     8             dp[i] = dp[i-1] + dp[i-2]
     9 
    10         return dp[-1]

    121. 买卖股票的最佳时机

    难度简单

    给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

    如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。

    注意你不能在买入股票前卖出股票。

    示例 1:

    输入: [7,1,5,3,6,4]
    输出: 5
    解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
         注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
    

    示例 2:

    输入: [7,6,4,3,1]
    输出: 0
    解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
     1 class Solution:
     2     def maxProfit(self, prices: List[int]) -> int:
     3         if not prices:
     4             return 0
     5         prices_len = len(prices)
     6         dp = [0 for _ in range(prices_len)]
     7 
     8         for i in range(1, prices_len):
     9             min_prices = min(prices[0:i])
    10             if min_prices < prices[i]:
    11                 dp[i] = prices[i] - min_prices
    12 
    13         return max(dp)

    5. 最长回文子串

    难度中等

    给定一个字符串 A,找到 A中最长的回文子串。你可以假设 A 的最大长度为 1000。

    示例 1:

    输入: "babad"
    输出: "bab"
    注意: "aba" 也是一个有效答案。
    

    示例 2:

    输入: "cbbd"
    输出: "bb"

    解答:
    #dp[i][j], 代表A[i:j+1]是否为回文串
    #dp[i][j] = dp[i+1][j-1] and A[i] == A[j]
     1 # -*- coding:utf-8 -*-
     2 
     3 class Solution:
     4     def getLongestPalindrome(self, A, n):
     5         # write code here
     6         if not A:
     7             return 0
     8         dp = [[False]*n for _ in range(n)]
     9 #         print(dp)
    10         for i_index in range(n):
    11             dp[i_index][i_index] = True
    12             if i_index+1 < n and A[i_index] == A[i_index+1]:
    13                 dp[i_index][i_index+1] = True
    14                 
    15         for i_index in range(n-3, -1, -1):
    16             for j_index in range(i_index+2, n):
    17                 if dp[i_index+1][j_index-1] and A[i_index] == A[j_index]:
    18                     dp[i_index][j_index] = True
    19         res = 1
    20         for i_index in range(n):
    21             for j_index in range(i_index, n):
    22                 if dp[i_index][j_index]:
    23                     res = max(res, j_index-i_index+1)
    24         print(res)
    25                 
    26         return res
    View Code
    
    

    516. 最长回文子序列

    难度中等

    给定一个字符串s,找到其中最长的回文子序列。可以假设s的最大长度为1000

    示例 1:
    输入:

    "bbbab"
    

    输出:

    4
    

    一个可能的最长回文子序列为 "bbbb"。

    示例 2:
    输入:

    "cbbd"
    

    输出:

    2
    

    一个可能的最长回文子序列为 "bb"。

     1 class Solution:
     2     def longestPalindromeSubseq(self, s: str) -> int:
     3         if not s:
     4             return 0
     5         n = len(s)
     6         dp = [[0] * n for _ in range(n)]
     7         for i in range(n):
     8             dp[i][i] = 1
     9 
    10         #dp[i][j] = dp[i+1][j-1] + 2 if s[i] == s[j]
    11         #dp[i][j] = max(dp[i+1][j], dp[i][j-1]) if s[i] != s[j]
    12         for i in range(n-1, -1, -1):
    13             for j in range(i+1, n):
    14                 if s[i] == s[j]:
    15                     dp[i][j] = dp[i+1][j-1] + 2
    16                 else:
    17                     dp[i][j] = max(dp[i+1][j], dp[i][j-1])
    18 
    19         return dp[0][n-1]
    View Code

    221. 最大正方形

    难度中等

    在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积。

    示例:

    输入: 
    
    1 0 1 0 0
    1 0 1 1 1
    1 1 1 1 1
    1 0 0 1 0
    
    输出: 4

    设定状态: dp[i][j] 表示以(i, j)为右下顶点的最大全1矩阵的边长.

    状态转移方程:

    if matrix[i][j] == 0
    	dp[i][j] = 0
    else                 // 此时为dp[i-1][j-1], dp[i-1][j], dp[i][j-1] 确定的区域的最大全1矩阵
    	dp[i][j] = min{dp[i-1][j-1], dp[i-1][j], dp[i][j-1]} + 1	// 得到此方程需要一定推导, 纸笔画一下
    

    边界: if i == 0 or j == 0: dp[i][j] = matrix[i][j]

     1 class Solution:
     2     def maximalSquare(self, matrix: List[List[str]]) -> int:
     3         if matrix == []:
     4             return 0
     5         # write your code here
     6         row, col = len(matrix), len(matrix[0])
     7         dp = [[0]*col for i in range(row)]
     8          
     9         for i in range(0, row):
    10             if matrix[i][0] == "1":
    11                 dp[i][0] = 1
    12          
    13         for j in range(0, col):
    14             if matrix[0][j] == "1":
    15                 dp[0][j] = 1
    16          
    17         for i in range(1, row):
    18             for j in range(1, col):
    19                 if matrix[i][j] == "1":
    20                     dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1])+1
    21                 else:
    22                     dp[i][j] = 0
    23          
    24         max_edge = max(max(dp[i]) for i in range(row))
    25 
    26         return max_edge*max_edge
    View Code

    300. 最长上升子序列

    难度中等

    给定一个无序的整数数组,找到其中最长上升子序列的长度。

    示例:

    输入: [10,9,2,5,3,7,101,18]
    输出: 4 
    解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4

    说明:

    • 可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
    • 你算法的时间复杂度应该为 O(n2) 。

    进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?

     1 class Solution:
     2     def lengthOfLIS(self, nums: List[int]) -> int:
     3         nums_len = len(nums)
     4         if nums_len <= 1:
     5             return nums_len
     6         #dp[i]代表着以nums[i]为结尾的最长上升子序列的长度
     7         dp = [1 for _ in range(nums_len)]
     8         
     9         for i in range(1, nums_len):
    10             for j in range(i):
    11                 if nums[i] > nums[j] and dp[j]+1 > dp[i]:
    12                     dp[i] = dp[j] + 1
    13         return max(dp)

    377. 组合总和 Ⅳ

    难度中等

    给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数。

    示例:

    nums = [1, 2, 3]
    target = 4
    
    所有可能的组合为:
    (1, 1, 1, 1)
    (1, 1, 2)
    (1, 2, 1)
    (1, 3)
    (2, 1, 1)
    (2, 2)
    (3, 1)
    
    请注意,顺序不同的序列被视作不同的组合。
    
    因此输出为 7。
     1 #动态规划
     2 class Solution:
     3     def combinationSum4(self, nums: List[int], target: int) -> int:
     4         nums_length = len(nums)
     5         if nums_length == 0:
     6             return 0
     7         
     8         dp = [0 for i in range(target+1)]
     9         
    10         dp[0] = 1 #赋初值,代表不选
    11         #dp[i]代表给定目标正整数i的组合的个数
    12         for i_index in range(1, target+1):
    13             for j_index in range(nums_length):
    14                 if nums[j_index] <= i_index:
    15                     dp[i_index] = dp[i_index] + dp[i_index-nums[j_index]]
    16 
    17         return dp[-1]
    View Code

    有些数的素因子只有 3,5,7,请设计一个算法找出第 k 个数。注意,不是必须有这些素因子,而是必须不包含其他的素因子。例如,前几个数按顺序应该是 1,3,5,7,9,15,21。

    示例 1:

    输入: k = 5
    
    输出: 9
     1 class Solution:
     2     def getKthMagicNumber(self, k: int) -> int:
     3         dp = [1 for _ in range(k)]
     4         dp[0] = 1
     5         for index in range(1, k):
     6             mini = float('inf')
     7             for ano_index in range(index):
     8                 temp3 = 3*dp[ano_index]
     9                 if 3*dp[ano_index] > dp[index-1]:
    10                     mini = min(mini, temp3)
    11                 temp5 = 5*dp[ano_index]
    12                 if temp5 > dp[index-1]:
    13                     mini = min(mini, temp5)
    14                 temp7 = 7*dp[ano_index]
    15                 if temp7 > dp[index-1]:
    16                     mini = min(mini, temp7)
    17 
    18             dp[index] = mini
    19 
    20         return dp[k-1]
    View Code

    NC116 把数字翻译成字符串

    题目描述

    有一种将字母编码成数字的方式:'a'->1, 'b->2', ... , 'z->26'。现在给一串数字,返回有多少种可能的译码结果

    示例1

    输入-"12"

    返回值-2

    说明--2种可能的译码结果(”ab” 或”l”)

    示例2

    输入-"31717126241541717"

    返回值-192

    说明

    192种可能的译码结果

    dp[i] 表示字符串nums中以i个位置结尾的前缀字符串的解码种数
    例如 nums = "123", 此时dp[0]=1,dp[1]=2,dp[2]=3

    分类讨论:

    1. 当前字符不等于0的时候,dp[i] = dp[i-1],此时将当前位置的一个字符译码

    2. 当前字符+前一个字符,记为num, 如果 10<=num<=26 此时符合两个合并一起译码的条件;

      • 若此时i等于1,直接dp[i]++;

      • 大于1, 则dp[i] += dp[i-2];

        • 举个例子: nums = "324"

        • 此时dp[0] = 1, dp[1]呢? dp[2]呢?

        • 很明显nums[1] != '0',所以dp[1] = dp[0],num = 32,此时不满足两个一起译码的条件则循环往下执行,此时 nums[2] != '0',则 dp[2] = dp[1] = 1, num = 24,此时满足两个一起译码的条件,因为i==2大于1,所以dp[2] += dp[2-2] ,dp[2] = 1+1 = 2。

    View Code

    NC92最长公共子序列

    题目描述

    给定两个字符串str1和str2,输出连个字符串的最长公共子序列。如过最长公共子序列为空,则输出-1。
    示例1

    输入:"1A2C3D4B56","B1D23CA45B6A"

     返回值: "123456"

    说明

    "123456"和“12C4B6”都是最长公共子序列,任意输出一个。

    View Code

    参考:https://blog.csdn.net/hrn1216/article/details/51534607

    NC 197 最长公共子串

    题目描述

    给定两个字符串str1和str2,输出两个字符串的最长公共子串,如果最长公共子串为空,输出-1。

    示例1

    输入

    "1AB2345CD","12345EF"

    返回值

    "2345"
    

    备注:

    1 <= |str_1|, |str_2| 5000

     1 #
     2 # longest common substring
     3 # @param str1 string字符串 the string
     4 # @param str2 string字符串 the string
     5 # @return string字符串
     6 #
     7 class Solution:
     8     def LCS(self , str1 , str2 ):
     9         # write code here
    10         #动态规划复杂度太高
    11 #         if not str1 or not str2:
    12 #             return -1
    13 #         str1_len = len(str1)
    14 #         str2_len = len(str2)
    15 #         dp = [[0]*(str2_len+1) for _ in range(str1_len+1)]
    16 #         max_value = 0
    17         
    18 #         for i in range(str1_len):
    19 #             if str2[0] == str1[i]:
    20 #                 dp[i][0] = 1
    21 #                 if dp[i][0] > max_value:
    22 #                     max_value = dp[i][0]
    23 #                     i_index = i
    24 #                     j_index = 0
    25                     
    26 #         for j in range(str2_len):
    27 #             if str1[0]== str2[j]:
    28 #                 dp[0][j] = 1
    29 #                 if dp[0][j] > max_value:
    30 #                     max_value = dp[0][j]
    31 #                     i_index = 0
    32 #                     j_index = j
    33         
    34 #         for i in range(str1_len):
    35 #             for j in range(str2_len):
    36 #                 if str1[i] == str2[j]:
    37 #                     dp[i+1][j+1] = dp[i][j] + 1
    38 #                     if dp[i+1][j+1] > max_value:
    39 #                         max_value = dp[i+1][j+1]
    40 #                         i_index = i+1
    41 #                         j_index = j+1
    42 #         return str1[i_index-max_value:i_index]
    43         if not str1 or not str2:
    44             return -1
    45         
    46         str1_len = len(str1)
    47         str2_len = len(str2)
    48         if str1_len > str2_len:
    49             str1, str2 = str2, str1
    50             str1_len, str2_len = str2_len, str1_len
    51             
    52         max_len = 0
    53         res = ''
    54         for i in range(str1_len):
    55             if str1[i-max_len:i+1] in str2:
    56                 res = str1[i-max_len:i+1]
    57                 max_len += 1
    58         if not res:
    59             return -1
    60         else:
    61             return res
    62         
    63         
    64         
    View Code

    NC35最小编辑代价

    题目描述

    给定两个字符串str1和str2,再给定三个整数ic,dc和rc,分别代表插入、删除和替换一个字符的代价,请输出将str1编辑成str2的最小代价。
    示例1

    输入:"abc","adc",5,3,2

    返回值:2

    示例2

    输入:"abc","adc",5,3,100

    返回值:8

    算法
    • 1.动态规划:dp[i][j]表示word1的前i个字符编辑成word2的前j个字符需要的最小操作数
    • 2.初始状态:dp[i][0] = i,i次删除;dp[0][i] = i,i次插入
    • 3.过渡公式:
      • 当i字符等于j字符时:dp[i][j] = dp[i-1][j-1],不需要额外操作
      • 当i字符不等于j字符时:dp[i][j] = Math.min(insert, delete, replace)
      • int insert = dp[i][j-1] + 1; i个编辑成j-1个字符,再插入一个j
      • int delete = dp[i-1][j] + 1; i-1个编辑成j个字母,再删除一个i
      • int replace = dp[i-1][j-1] + 1; i-1个编辑成j-1个字母,再将i替换成j
    View Code

    NC 字段数字和

    题目描述

    给出一个n个数字的序列a_1,a_2,dots a_na1,a2,an,你想知道所有长度大于等于k的连续子段中,子段数字和最大可以是多少。

    连续子段指的是序列中一段连续的数字。子段数字和指的是子段中所有数字相加的和。
     
    dp[i]表示以“第i个数字结尾”的子段最大和
    sum[i]表示从第1个数字到第i个数字的和(sum[i]-sum[i-k]自然就表示,从第i-k+1到i,共k个数的和)
    dp[i]可以选择继承--->dp[i-1]+a[i-1],也可以“另起炉灶”--->dp[i]=sum[i]-sum[i-k]
    故dp[i]=max(dp[i-1]+a[i-1],sum[i]-sum[i-k]) 
    View Code

     NC 107 寻找峰值

    题目描述

    山峰元素是指其值大于或等于左右相邻值的元素。给定一个输入数组nums,任意两个相邻元素值不相等,数组可能包含多个山峰。找到索引最大的那个山峰元素并返回其索引。

    假设 nums[-1] = nums[n] = -∞。

    示例1

    输入

    [2,4,1,2,7,8,4]

    返回值

    5

     1 #
     2 # 寻找最后的山峰
     3 # @param a int整型一维数组 
     4 # @return int整型
     5 #
     6 class Solution:
     7     def solve(self , a ):
     8         # write code here
     9         if not a:
    10             return 0
    11         a_len = len(a)
    12         if a_len == 1:
    13             return 0
    14         
    15         dp = [False for _ in range(a_len)]
    16         dp[0] = True if a[0]> a[1] else False
    17         if a[a_len-1] > a[a_len-2]:
    18             return a_len-1
    19         
    20         for i in range(1, a_len-1):
    21             if a[i-1]<a[i] and a[i+1]<a[i]:
    22                 dp[i] = True
    23         for i in range(a_len-2, -1, -1):
    24             if dp[i]:
    25                 return i
    26         return 0
    View Code
  • 相关阅读:
    synchronized关键字原理
    http几种请求格式总结
    logback配置
    docker部署nacos单机
    Diango migrate遇到问题
    pip安装ujson报错: error:Microsoft Visual C++ 14.0 is required
    vue watch监听新增属性
    git commit message规范与约束(全局安装)
    git commit message规范与约束(项目内安装)
    pip常用方法
  • 原文地址:https://www.cnblogs.com/dede-0119/p/12499569.html
Copyright © 2020-2023  润新知