动态规划

难度简单

给定一个整数数组 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

 

posted @ 2020-03-24 11:07  aiwenhua_0610  阅读(237)  评论(0编辑  收藏  举报