mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-12 05:20:59 +08:00
@ -148,6 +148,8 @@ class Solution {
|
|||||||
```
|
```
|
||||||
|
|
||||||
Python:
|
Python:
|
||||||
|
|
||||||
|
DP
|
||||||
```python
|
```python
|
||||||
class Solution:
|
class Solution:
|
||||||
def lengthOfLIS(self, nums: List[int]) -> int:
|
def lengthOfLIS(self, nums: List[int]) -> int:
|
||||||
@ -162,7 +164,31 @@ class Solution:
|
|||||||
result = max(result, dp[i]) #取长的子序列
|
result = max(result, dp[i]) #取长的子序列
|
||||||
return result
|
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:
|
||||||
```go
|
```go
|
||||||
// 动态规划求解
|
// 动态规划求解
|
||||||
|
@ -248,23 +248,51 @@ class Solution {
|
|||||||
```
|
```
|
||||||
|
|
||||||
Python:
|
Python:
|
||||||
|
版本一
|
||||||
```python
|
```python
|
||||||
|
from typing import List
|
||||||
|
|
||||||
class Solution:
|
class Solution:
|
||||||
def maxProfit(self, prices: List[int]) -> int:
|
def maxProfit(self, prices: List[int]) -> int:
|
||||||
n = len(prices)
|
n = len(prices)
|
||||||
if n == 0:
|
if n == 0:
|
||||||
return 0
|
return 0
|
||||||
dp = [[0] * 4 for _ in range(n)]
|
dp = [[0] * 4 for _ in range(n)] # 创建动态规划数组,4个状态分别表示持有股票、不持有股票且处于冷冻期、不持有股票且不处于冷冻期、不持有股票且当天卖出后处于冷冻期
|
||||||
dp[0][0] = -prices[0] #持股票
|
dp[0][0] = -prices[0] # 初始状态:第一天持有股票的最大利润为买入股票的价格
|
||||||
for i in range(1, n):
|
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][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][1] = max(dp[i-1][1], dp[i-1][3]) # 当前不持有股票且处于冷冻期的最大利润等于前一天持有股票的最大利润加上当前股票的价格
|
||||||
dp[i][2] = dp[i-1][0] + prices[i]
|
dp[i][2] = dp[i-1][0] + prices[i] # 当前不持有股票且不处于冷冻期的最大利润等于前一天不持有股票的最大利润或者前一天处于冷冻期的最大利润
|
||||||
dp[i][3] = dp[i-1][2]
|
dp[i][3] = dp[i-1][2] # 当前不持有股票且当天卖出后处于冷冻期的最大利润等于前一天不持有股票且不处于冷冻期的最大利润
|
||||||
return max(dp[n-1][3], dp[n-1][1], dp[n-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:
|
||||||
```go
|
```go
|
||||||
// 最佳买卖股票时机含冷冻期 动态规划
|
// 最佳买卖股票时机含冷冻期 动态规划
|
||||||
|
@ -208,7 +208,7 @@ public static int findLengthOfLCIS(int[] nums) {
|
|||||||
|
|
||||||
Python:
|
Python:
|
||||||
|
|
||||||
> 动态规划:
|
DP
|
||||||
```python
|
```python
|
||||||
class Solution:
|
class Solution:
|
||||||
def findLengthOfLCIS(self, nums: List[int]) -> int:
|
def findLengthOfLCIS(self, nums: List[int]) -> int:
|
||||||
@ -223,8 +223,27 @@ class Solution:
|
|||||||
return result
|
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
|
```python
|
||||||
class Solution:
|
class Solution:
|
||||||
def findLengthOfLCIS(self, nums: List[int]) -> int:
|
def findLengthOfLCIS(self, nums: List[int]) -> int:
|
||||||
|
@ -302,37 +302,99 @@ class Solution {
|
|||||||
|
|
||||||
Python:
|
Python:
|
||||||
|
|
||||||
> 动态规划:
|
2维DP
|
||||||
```python
|
```python
|
||||||
class Solution:
|
class Solution:
|
||||||
def findLength(self, A: List[int], B: List[int]) -> int:
|
def findLength(self, nums1: List[int], nums2: List[int]) -> int:
|
||||||
dp = [[0] * (len(B)+1) for _ in range(len(A)+1)]
|
# 创建一个二维数组 dp,用于存储最长公共子数组的长度
|
||||||
|
dp = [[0] * (len(nums2) + 1) for _ in range(len(nums1) + 1)]
|
||||||
|
# 记录最长公共子数组的长度
|
||||||
result = 0
|
result = 0
|
||||||
for i in range(1, len(A)+1):
|
|
||||||
for j in range(1, len(B)+1):
|
# 遍历数组 nums1
|
||||||
if A[i-1] == B[j-1]:
|
for i in range(1, len(nums1) + 1):
|
||||||
dp[i][j] = dp[i-1][j-1] + 1
|
# 遍历数组 nums2
|
||||||
result = max(result, dp[i][j])
|
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
|
return result
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
> 动态规划:滚动数组
|
1维DP
|
||||||
```python
|
```python
|
||||||
class Solution:
|
class Solution:
|
||||||
def findLength(self, A: List[int], B: List[int]) -> int:
|
def findLength(self, nums1: List[int], nums2: List[int]) -> int:
|
||||||
dp = [0] * (len(B) + 1)
|
# 创建一个一维数组 dp,用于存储最长公共子数组的长度
|
||||||
|
dp = [0] * (len(nums2) + 1)
|
||||||
|
# 记录最长公共子数组的长度
|
||||||
result = 0
|
result = 0
|
||||||
for i in range(1, len(A)+1):
|
|
||||||
for j in range(len(B), 0, -1):
|
# 遍历数组 nums1
|
||||||
if A[i-1] == B[j-1]:
|
for i in range(1, len(nums1) + 1):
|
||||||
dp[j] = dp[j-1] + 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:
|
else:
|
||||||
dp[j] = 0 #注意这里不相等的时候要有赋0的操作
|
# 如果不相等,将当前位置的值置为零
|
||||||
result = max(result, dp[j])
|
dp[j] = 0
|
||||||
|
# 更新 prev 变量为当前位置的值,供下一次迭代使用
|
||||||
|
prev = current
|
||||||
|
|
||||||
|
# 返回最长公共子数组的长度
|
||||||
return result
|
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:
|
||||||
```Go
|
```Go
|
||||||
func findLength(A []int, B []int) int {
|
func findLength(A []int, B []int) int {
|
||||||
|
@ -203,21 +203,49 @@ class Solution {
|
|||||||
```
|
```
|
||||||
|
|
||||||
Python:
|
Python:
|
||||||
|
2维DP
|
||||||
```python
|
```python
|
||||||
class Solution:
|
class Solution:
|
||||||
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
|
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
|
||||||
len1, len2 = len(text1)+1, len(text2)+1
|
# 创建一个二维数组 dp,用于存储最长公共子序列的长度
|
||||||
dp = [[0 for _ in range(len1)] for _ in range(len2)] # 先对dp数组做初始化操作
|
dp = [[0] * (len(text2) + 1) for _ in range(len(text1) + 1)]
|
||||||
for i in range(1, len2):
|
|
||||||
for j in range(1, len1): # 开始列出状态转移方程
|
# 遍历 text1 和 text2,填充 dp 数组
|
||||||
if text1[j-1] == text2[i-1]:
|
for i in range(1, len(text1) + 1):
|
||||||
dp[i][j] = dp[i-1][j-1]+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:
|
else:
|
||||||
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
|
# 如果 text1[i-1] 和 text2[j-1] 不相等,则当前位置的最长公共子序列长度为上方或左方的较大值
|
||||||
return dp[-1][-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:
|
||||||
```Go
|
```Go
|
||||||
|
Reference in New Issue
Block a user