diff --git a/problems/0001.两数之和.md b/problems/0001.两数之和.md index 56cff527..aa8724db 100644 --- a/problems/0001.两数之和.md +++ b/problems/0001.两数之和.md @@ -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存放的就是我们访问过的元素。 diff --git a/problems/0045.跳跃游戏II.md b/problems/0045.跳跃游戏II.md index 7dbf531b..d4f2e6ea 100644 --- a/problems/0045.跳跃游戏II.md +++ b/problems/0045.跳跃游戏II.md @@ -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 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: diff --git a/problems/0322.零钱兑换.md b/problems/0322.零钱兑换.md index 01455427..c718ef47 100644 --- a/problems/0322.零钱兑换.md +++ b/problems/0322.零钱兑换.md @@ -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 ``` diff --git a/problems/0343.整数拆分.md b/problems/0343.整数拆分.md index bc69c5c4..4170f7e6 100644 --- a/problems/0343.整数拆分.md +++ b/problems/0343.整数拆分.md @@ -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)); } } diff --git a/problems/0416.分割等和子集.md b/problems/0416.分割等和子集.md index 7cf5bcfb..45dd289a 100644 --- a/problems/0416.分割等和子集.md +++ b/problems/0416.分割等和子集.md @@ -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,说明背包装满了。 diff --git a/problems/0674.最长连续递增序列.md b/problems/0674.最长连续递增序列.md index 81155f9b..3cb68060 100644 --- a/problems/0674.最长连续递增序列.md +++ b/problems/0674.最长连续递增序列.md @@ -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]。 diff --git a/problems/0763.划分字母区间.md b/problems/0763.划分字母区间.md index 96dc724d..6c4f1c5e 100644 --- a/problems/0763.划分字母区间.md +++ b/problems/0763.划分字母区间.md @@ -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 diff --git a/problems/背包理论基础01背包-2.md b/problems/背包理论基础01背包-2.md index 11c41470..c9414fd6 100644 --- a/problems/背包理论基础01背包-2.md +++ b/problems/背包理论基础01背包-2.md @@ -142,7 +142,7 @@ dp[1] = dp[1 - weight[0]] + value[0] = 15 倒序遍历的原因是,本质上还是一个对二维数组的遍历,并且右下角的值依赖上一层左上角的值,因此需要保证左边的值仍然是上一层的,从右向左覆盖。 -(这里如果读不懂,就在回想一下dp[j]的定义,或者就把两个for循环顺序颠倒一下试试!) +(这里如果读不懂,就再回想一下dp[j]的定义,或者就把两个for循环顺序颠倒一下试试!) **所以一维dp数组的背包在遍历顺序上和二维其实是有很大差异的!**,这一点大家一定要注意。