mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-07 15:45:40 +08:00
Merge branch 'master' of github.com:youngyangyang04/leetcode-master
This commit is contained in:
@ -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对应的就是value,value用来存下标。
|
||||
|
||||
所以 map中的存储结构为 {key:数据元素,value:数组元素对应的下表}。
|
||||
所以 map中的存储结构为 {key:数据元素,value:数组元素对应的下标}。
|
||||
|
||||
在遍历数组的时候,只需要向map去查询是否有和目前遍历元素比配的数值,如果有,就找到的匹配对,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素。
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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
|
||||
```
|
||||
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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,说明背包装满了。
|
||||
|
||||
|
@ -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]。
|
||||
|
||||
|
@ -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
|
||||
|
@ -142,7 +142,7 @@ dp[1] = dp[1 - weight[0]] + value[0] = 15
|
||||
|
||||
倒序遍历的原因是,本质上还是一个对二维数组的遍历,并且右下角的值依赖上一层左上角的值,因此需要保证左边的值仍然是上一层的,从右向左覆盖。
|
||||
|
||||
(这里如果读不懂,就在回想一下dp[j]的定义,或者就把两个for循环顺序颠倒一下试试!)
|
||||
(这里如果读不懂,就再回想一下dp[j]的定义,或者就把两个for循环顺序颠倒一下试试!)
|
||||
|
||||
**所以一维dp数组的背包在遍历顺序上和二维其实是有很大差异的!**,这一点大家一定要注意。
|
||||
|
||||
|
Reference in New Issue
Block a user