Merge branch 'master' of github.com:youngyangyang04/leetcode-master

This commit is contained in:
programmercarl
2023-02-08 17:28:13 +08:00
11 changed files with 76 additions and 13 deletions

View File

@ -69,7 +69,7 @@ std::unordered_map 底层实现为哈希表std::map 和std::multimap 的底
* **map用来做什么**
* **map中key和value分别表示什么**
map目的用来存放我们访问过的元素因为遍历数组的时候需要记录我们之前遍历过哪些元素和对应的下这样才能找到与当前元素相匹配的也就是相加等于target
map目的用来存放我们访问过的元素因为遍历数组的时候需要记录我们之前遍历过哪些元素和对应的下这样才能找到与当前元素相匹配的也就是相加等于target
接下来是map中key和value分别表示什么。
@ -77,7 +77,7 @@ map目的用来存放我们访问过的元素因为遍历数组的时候
那么判断元素是否出现这个元素就要作为key所以数组中的元素作为key有key对应的就是valuevalue用来存下标。
所以 map中的存储结构为 {key数据元素value数组元素对应的下}。
所以 map中的存储结构为 {key数据元素value数组元素对应的下}。
在遍历数组的时候只需要向map去查询是否有和目前遍历元素比配的数值如果有就找到的匹配对如果没有就把目前遍历的元素放进map中因为map存放的就是我们访问过的元素。

View File

@ -229,7 +229,19 @@ class Solution:
step += 1
return step
```
```python
# 动态规划做法
class Solution:
def jump(self, nums: List[int]) -> int:
result = [10**4+1]*len(nums)
result[0]=0
for i in range(len(nums)):
for j in range(nums[i]+1):
if i+j<len(nums): result[i+j]=min(result[i+j],result[i]+1)
#print(result) #打印数组
return result[-1]
```
### Go

View File

@ -338,6 +338,10 @@ class Solution:
```go
func uniquePathsWithObstacles(obstacleGrid [][]int) int {
m, n := len(obstacleGrid), len(obstacleGrid[0])
//如果在起点或终点出现了障碍直接返回0
if obstacleGrid[m-1][n-1] == 1 || obstacleGrid[0][0] == 1 {
return 0
}
// 定义一个dp数组
dp := make([][]int, m)
for i, _ := range dp {
@ -362,8 +366,6 @@ func uniquePathsWithObstacles(obstacleGrid [][]int) int {
}
return dp[m-1][n-1]
}
```
### Javascript

View File

@ -120,7 +120,7 @@ dp[i][4] = max(dp[i - 1][4], dp[i - 1][3] + prices[i]);
大家可以看到红色框为最后两次卖出的状态。
现在最大的时候一定是卖出的状态,而两次卖出的状态现金最大一定是最后一次卖出。
现在最大的时候一定是卖出的状态,而两次卖出的状态现金最大一定是最后一次卖出。如果想不明白的录友也可以这么理解如果第一次卖出已经是最大值了那么我们可以在当天立刻买入再立刻卖出。所以dp[4][4]已经包含了dp[4][2]的情况。也就是说第二次卖出手里所剩的钱一定是最多的。
所以最终最大利润是dp[4][4]

View File

@ -228,7 +228,22 @@ class Solution:
```
Python递归法从后向前
```python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if not head or not head.next: return head
p = self.reverseList(head.next)
head.next.next = head
head.next = None
return p
```
Go

View File

@ -215,19 +215,19 @@ class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
'''版本一'''
# 初始化
dp = [amount + 1]*(amount + 1)
dp = [float("inf")]*(amount + 1)
dp[0] = 0
# 遍历物品
for coin in coins:
# 遍历背包
for j in range(coin, amount + 1):
dp[j] = min(dp[j], dp[j - coin] + 1)
return dp[amount] if dp[amount] < amount + 1 else -1
return dp[amount] if dp[amount] != float("inf") else -1
def coinChange1(self, coins: List[int], amount: int) -> int:
'''版本二'''
# 初始化
dp = [amount + 1]*(amount + 1)
dp = [float("inf")]*(amount + 1)
dp[0] = 0
# 遍历物品
for j in range(1, amount + 1):
@ -235,7 +235,7 @@ class Solution:
for coin in coins:
if j >= coin:
dp[j] = min(dp[j], dp[j - coin] + 1)
return dp[amount] if dp[amount] < amount + 1 else -1
return dp[amount] if dp[amount] != float("inf") else -1
```

View File

@ -94,7 +94,7 @@ dp[i] 是依靠 dp[i - j]的状态所以遍历i一定是从前向后遍历
所以遍历顺序为:
```CPP
for (int i = 3; i <= n ; i++) {
for (int j = 1; j <= i / 2; j++) {
for (int j = 1; j < i - 1; j++) {
dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
}
}

View File

@ -92,7 +92,7 @@
有录友可能想,那还有装不满的时候?
拿输入数组 [1, 5, 11, 5]距离 dp[7] 只能等于 6因为 只能放进 1 和 5。
拿输入数组 [1, 5, 11, 5]举例 dp[7] 只能等于 6因为 只能放进 1 和 5。
而dp[6] 就可以等于6了放进1 和 5那么dp[6] == 6说明背包装满了。

View File

@ -52,7 +52,7 @@
**注意这里就体现出和[动态规划300.最长递增子序列](https://programmercarl.com/0300.最长上升子序列.html)的区别!**
因为本题要求连续递增子序列,所以就要比较nums[i]与nums[i - 1]而不用去比较nums[j]与nums[i] j是在0到i之间遍历
因为本题要求连续递增子序列,所以就要比较nums[i]与nums[i - 1]而不用去比较nums[j]与nums[i] j是在0到i之间遍历
既然不用j了那么也不用两层for循环本题一层for循环就行比较nums[i] 和 nums[i - 1]。

View File

@ -242,6 +242,40 @@ class Solution:
left = i + 1
return result
# 解法二(不相交区间法)
class Solution:
def partitionLabels(self, s: str) -> List[int]:
# 记录每个字母出现的区间
def getBord(s):
hash = [[-float('inf')] * 2 for _ in range(26)]
for i in range(len(s)):
if hash[ord(s[i]) - ord('a')][0] == -float('inf'):
hash[ord(s[i]) - ord('a')][0] = i
hash[ord(s[i]) - ord('a')][1] = i
# 去除字符串中未出现的字母所占用区间
hash_filter = []
for item in hash:
if item[0] != -float('inf'): hash_filter.append(item)
return hash_filter
# 得到无重叠区间题意中的输入样例格式:区间列表
hash = getBord(s)
# 按照左边界从小到大排序
hash.sort(key= lambda x: x[0])
res = []
left = 0
# 记录最大右边界
right = hash[0][1]
for i in range(len(hash)):
# 一旦下一区间左边界大于当前右边界,即可认为出现分割点
if hash[i][0] > right:
res.append(right - left + 1)
left = hash[i][0]
# 实时更新最大右边界
right = max(right, hash[i][1])
# 最右侧区间字符串长度为1时的特殊情况也包含于其中
res.append(right - left + 1)
return res
```
### Go

View File

@ -142,7 +142,7 @@ dp[1] = dp[1 - weight[0]] + value[0] = 15
倒序遍历的原因是,本质上还是一个对二维数组的遍历,并且右下角的值依赖上一层左上角的值,因此需要保证左边的值仍然是上一层的,从右向左覆盖。
(这里如果读不懂,就回想一下dp[j]的定义或者就把两个for循环顺序颠倒一下试试
(这里如果读不懂,就回想一下dp[j]的定义或者就把两个for循环顺序颠倒一下试试
**所以一维dp数组的背包在遍历顺序上和二维其实是有很大差异的**,这一点大家一定要注意。