Merge pull request #2133 from jianghongcheng/master

merge
This commit is contained in:
程序员Carl
2023-06-12 07:00:09 +08:00
committed by GitHub
5 changed files with 201 additions and 38 deletions

View File

@ -148,6 +148,8 @@ class Solution {
```
Python
DP
```python
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
@ -162,7 +164,31 @@ class Solution:
result = max(result, dp[i]) #取长的子序列
return result
```
贪心
```python
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
if len(nums) <= 1:
return len(nums)
tails = [nums[0]] # 存储递增子序列的尾部元素
for num in nums[1:]:
if num > tails[-1]:
tails.append(num) # 如果当前元素大于递增子序列的最后一个元素,直接加入到子序列末尾
else:
# 使用二分查找找到当前元素在递增子序列中的位置,并替换对应位置的元素
left, right = 0, len(tails) - 1
while left < right:
mid = (left + right) // 2
if tails[mid] < num:
left = mid + 1
else:
right = mid
tails[left] = num
return len(tails) # 返回递增子序列的长度
```
Go
```go
// 动态规划求解

View File

@ -248,23 +248,51 @@ class Solution {
```
Python
版本一
```python
from typing import List
class Solution:
def maxProfit(self, prices: List[int]) -> int:
n = len(prices)
if n == 0:
return 0
dp = [[0] * 4 for _ in range(n)]
dp[0][0] = -prices[0] #持股票
dp = [[0] * 4 for _ in range(n)] # 创建动态规划数组4个状态分别表示持有股票、不持有股票且处于冷冻期、不持有股票且不处于冷冻期、不持有股票且当天卖出后处于冷冻期
dp[0][0] = -prices[0] # 初始状态:第一天持有股票的最大利润为买入股票的价格
for i in range(1, n):
dp[i][0] = max(dp[i-1][0], max(dp[i-1][3], dp[i-1][1]) - prices[i])
dp[i][1] = max(dp[i-1][1], dp[i-1][3])
dp[i][2] = dp[i-1][0] + prices[i]
dp[i][3] = dp[i-1][2]
return max(dp[n-1][3], dp[n-1][1], dp[n-1][2])
```
dp[i][0] = max(dp[i-1][0], max(dp[i-1][3], dp[i-1][1]) - prices[i]) # 当前持有股票的最大利润等于前一天持有股票的最大利润或者前一天不持有股票且不处于冷冻期的最大利润减去当前股票的价格
dp[i][1] = max(dp[i-1][1], dp[i-1][3]) # 当前不持有股票且处于冷冻期的最大利润等于前一天持有股票的最大利润加上当前股票的价格
dp[i][2] = dp[i-1][0] + prices[i] # 当前不持有股票且不处于冷冻期的最大利润等于前一天不持有股票的最大利润或者前一天处于冷冻期的最大利润
dp[i][3] = dp[i-1][2] # 当前不持有股票且当天卖出后处于冷冻期的最大利润等于前一天不持有股票且不处于冷冻期的最大利润
return max(dp[n-1][3], dp[n-1][1], dp[n-1][2]) # 返回最后一天不持有股票的最大利润
```
版本二
```python
class Solution:
def maxProfit(self, prices: List[int]) -> int:
n = len(prices)
if n < 2:
return 0
# 定义三种状态的动态规划数组
dp = [[0] * 3 for _ in range(n)]
dp[0][0] = -prices[0] # 持有股票的最大利润
dp[0][1] = 0 # 不持有股票,且处于冷冻期的最大利润
dp[0][2] = 0 # 不持有股票,不处于冷冻期的最大利润
for i in range(1, n):
# 当前持有股票的最大利润等于前一天持有股票的最大利润或者前一天不持有股票且不处于冷冻期的最大利润减去当前股票的价格
dp[i][0] = max(dp[i-1][0], dp[i-1][2] - prices[i])
# 当前不持有股票且处于冷冻期的最大利润等于前一天持有股票的最大利润加上当前股票的价格
dp[i][1] = dp[i-1][0] + prices[i]
# 当前不持有股票且不处于冷冻期的最大利润等于前一天不持有股票的最大利润或者前一天处于冷冻期的最大利润
dp[i][2] = max(dp[i-1][2], dp[i-1][1])
# 返回最后一天不持有股票的最大利润
return max(dp[-1][1], dp[-1][2])
```
Go
```go
// 最佳买卖股票时机含冷冻期 动态规划

View File

@ -208,7 +208,7 @@ public static int findLengthOfLCIS(int[] nums) {
Python
> 动态规划:
DP
```python
class Solution:
def findLengthOfLCIS(self, nums: List[int]) -> int:
@ -223,8 +223,27 @@ class Solution:
return result
```
DP(优化版)
```python
class Solution:
def findLengthOfLCIS(self, nums: List[int]) -> int:
if not nums:
return 0
> 贪心法:
max_length = 1
current_length = 1
for i in range(1, len(nums)):
if nums[i] > nums[i - 1]:
current_length += 1
max_length = max(max_length, current_length)
else:
current_length = 1
return max_length
```
贪心
```python
class Solution:
def findLengthOfLCIS(self, nums: List[int]) -> int:

View File

@ -302,37 +302,99 @@ class Solution {
Python
> 动态规划:
2维DP
```python
class Solution:
def findLength(self, A: List[int], B: List[int]) -> int:
dp = [[0] * (len(B)+1) for _ in range(len(A)+1)]
def findLength(self, nums1: List[int], nums2: List[int]) -> int:
# 创建一个二维数组 dp用于存储最长公共子数组的长度
dp = [[0] * (len(nums2) + 1) for _ in range(len(nums1) + 1)]
# 记录最长公共子数组的长度
result = 0
for i in range(1, len(A)+1):
for j in range(1, len(B)+1):
if A[i-1] == B[j-1]:
dp[i][j] = dp[i-1][j-1] + 1
result = max(result, dp[i][j])
# 遍历数组 nums1
for i in range(1, len(nums1) + 1):
# 遍历数组 nums2
for j in range(1, len(nums2) + 1):
# 如果 nums1[i-1] 和 nums2[j-1] 相等
if nums1[i - 1] == nums2[j - 1]:
# 在当前位置上的最长公共子数组长度为前一个位置上的长度加一
dp[i][j] = dp[i - 1][j - 1] + 1
# 更新最长公共子数组的长度
if dp[i][j] > result:
result = dp[i][j]
# 返回最长公共子数组的长度
return result
```
> 动态规划:滚动数组
1维DP
```python
class Solution:
def findLength(self, A: List[int], B: List[int]) -> int:
dp = [0] * (len(B) + 1)
def findLength(self, nums1: List[int], nums2: List[int]) -> int:
# 创建一个一维数组 dp用于存储最长公共子数组的长度
dp = [0] * (len(nums2) + 1)
# 记录最长公共子数组的长度
result = 0
for i in range(1, len(A)+1):
for j in range(len(B), 0, -1):
if A[i-1] == B[j-1]:
dp[j] = dp[j-1] + 1
# 遍历数组 nums1
for i in range(1, len(nums1) + 1):
# 用于保存上一个位置的值
prev = 0
# 遍历数组 nums2
for j in range(1, len(nums2) + 1):
# 保存当前位置的值,因为会在后面被更新
current = dp[j]
# 如果 nums1[i-1] 和 nums2[j-1] 相等
if nums1[i - 1] == nums2[j - 1]:
# 在当前位置上的最长公共子数组长度为上一个位置的长度加一
dp[j] = prev + 1
# 更新最长公共子数组的长度
if dp[j] > result:
result = dp[j]
else:
dp[j] = 0 #注意这里不相等的时候要有赋0的操作
result = max(result, dp[j])
# 如果不相等,将当前位置的值置为零
dp[j] = 0
# 更新 prev 变量为当前位置的值,供下一次迭代使用
prev = current
# 返回最长公共子数组的长度
return result
```
2维DP 扩展
```python
class Solution:
def findLength(self, nums1: List[int], nums2: List[int]) -> int:
# 创建一个二维数组 dp用于存储最长公共子数组的长度
dp = [[0] * (len(nums2) + 1) for _ in range(len(nums1) + 1)]
# 记录最长公共子数组的长度
result = 0
# 对第一行和第一列进行初始化
for i in range(len(nums1)):
if nums1[i] == nums2[0]:
dp[i + 1][1] = 1
for j in range(len(nums2)):
if nums1[0] == nums2[j]:
dp[1][j + 1] = 1
# 填充dp数组
for i in range(1, len(nums1) + 1):
for j in range(1, len(nums2) + 1):
if nums1[i - 1] == nums2[j - 1]:
# 如果 nums1[i-1] 和 nums2[j-1] 相等,则当前位置的最长公共子数组长度为左上角位置的值加一
dp[i][j] = dp[i - 1][j - 1] + 1
if dp[i][j] > result:
# 更新最长公共子数组的长度
result = dp[i][j]
# 返回最长公共子数组的长度
return result
```
Go
```Go
func findLength(A []int, B []int) int {

View File

@ -203,21 +203,49 @@ class Solution {
```
Python
2维DP
```python
class Solution:
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
len1, len2 = len(text1)+1, len(text2)+1
dp = [[0 for _ in range(len1)] for _ in range(len2)] # 先对dp数组做初始化操作
for i in range(1, len2):
for j in range(1, len1): # 开始列出状态转移方程
if text1[j-1] == text2[i-1]:
dp[i][j] = dp[i-1][j-1]+1
# 创建一个二维数组 dp用于存储最长公共子序列的长度
dp = [[0] * (len(text2) + 1) for _ in range(len(text1) + 1)]
# 遍历 text1 和 text2填充 dp 数组
for i in range(1, len(text1) + 1):
for j in range(1, len(text2) + 1):
if text1[i - 1] == text2[j - 1]:
# 如果 text1[i-1] 和 text2[j-1] 相等,则当前位置的最长公共子序列长度为左上角位置的值加一
dp[i][j] = dp[i - 1][j - 1] + 1
else:
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
return dp[-1][-1]
```
# 如果 text1[i-1] 和 text2[j-1] 不相等,则当前位置的最长公共子序列长度为上方或左方的较大值
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
# 返回最长公共子序列的长度
return dp[len(text1)][len(text2)]
```
1维DP
```python
class Solution:
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
m, n = len(text1), len(text2)
dp = [0] * (n + 1) # 初始化一维DP数组
for i in range(1, m + 1):
prev = 0 # 保存上一个位置的最长公共子序列长度
for j in range(1, n + 1):
curr = dp[j] # 保存当前位置的最长公共子序列长度
if text1[i - 1] == text2[j - 1]:
# 如果当前字符相等,则最长公共子序列长度加一
dp[j] = prev + 1
else:
# 如果当前字符不相等,则选择保留前一个位置的最长公共子序列长度中的较大值
dp[j] = max(dp[j], dp[j - 1])
prev = curr # 更新上一个位置的最长公共子序列长度
return dp[n] # 返回最后一个位置的最长公共子序列长度作为结果
```
Go
```Go