From d9887223965e84771503808e5685c1307998fabe Mon Sep 17 00:00:00 2001 From: jianghongcheng <35664721+jianghongcheng@users.noreply.github.com> Date: Wed, 31 May 2023 23:44:40 -0500 Subject: [PATCH 01/10] =?UTF-8?q?Update=200053.=E6=9C=80=E5=A4=A7=E5=AD=90?= =?UTF-8?q?=E5=BA=8F=E5=92=8C.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0053.最大子序和.md | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/problems/0053.最大子序和.md b/problems/0053.最大子序和.md index 48f8be29..bc5e1d55 100644 --- a/problems/0053.最大子序和.md +++ b/problems/0053.最大子序和.md @@ -198,21 +198,35 @@ class Solution { ``` ### Python - +暴力法 ```python class Solution: - def maxSubArray(self, nums: List[int]) -> int: - result = -float('inf') + def maxSubArray(self, nums): + result = float('-inf') # 初始化结果为负无穷大 + count = 0 + for i in range(len(nums)): # 设置起始位置 + count = 0 + for j in range(i, len(nums)): # 从起始位置i开始遍历寻找最大值 + count += nums[j] + result = max(count, result) # 更新最大值 + return result + +``` +```python +class Solution: + def maxSubArray(self, nums): + result = float('-inf') # 初始化结果为负无穷大 count = 0 for i in range(len(nums)): count += nums[i] - if count > result: + if count > result: # 取区间累计的最大值(相当于不断确定最大子序终止位置) result = count - if count <= 0: + if count <= 0: # 相当于重置最大子序起始位置,因为遇到负数一定是拉低总和 count = 0 return result -``` + +``` ### Go ```go From d65f7a32da277ab0020c3104c6cc3f51b0e51998 Mon Sep 17 00:00:00 2001 From: jianghongcheng <35664721+jianghongcheng@users.noreply.github.com> Date: Thu, 1 Jun 2023 00:41:29 -0500 Subject: [PATCH 02/10] =?UTF-8?q?Update=200045.=E8=B7=B3=E8=B7=83=E6=B8=B8?= =?UTF-8?q?=E6=88=8FII.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0045.跳跃游戏II.md | 115 ++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 50 deletions(-) diff --git a/problems/0045.跳跃游戏II.md b/problems/0045.跳跃游戏II.md index 8a939582..2f0349b2 100644 --- a/problems/0045.跳跃游戏II.md +++ b/problems/0045.跳跃游戏II.md @@ -205,66 +205,81 @@ class Solution { ``` ### Python - +贪心(版本一) ```python class Solution: - def jump(self, nums: List[int]) -> int: - if len(nums) == 1: return 0 - ans = 0 - curDistance = 0 - nextDistance = 0 - for i in range(len(nums)): - nextDistance = max(i + nums[i], nextDistance) - if i == curDistance: - if curDistance != len(nums) - 1: - ans += 1 - curDistance = nextDistance - if nextDistance >= len(nums) - 1: break - return ans -``` - -```python -# 贪心版本二 -class Solution: - def jump(self, nums: List[int]) -> int: + def jump(self, nums): if len(nums) == 1: return 0 - curDistance, nextDistance = 0, 0 - step = 0 - for i in range(len(nums)-1): - nextDistance = max(nextDistance, nums[i]+i) - if i == curDistance: - curDistance = nextDistance - step += 1 - return step -``` -```python -# 贪心版本三 - 类似‘55-跳跃游戏’写法 -class Solution: - def jump(self, nums) -> int: - if len(nums)==1: return 0 - i = 0 - count = 0 - cover = 0 - while i<=cover: - for i in range(i,cover+1): - cover = max(nums[i]+i,cover) - if cover>=len(nums)-1: return count+1 - count+=1 + cur_distance = 0 # 当前覆盖最远距离下标 + ans = 0 # 记录走的最大步数 + next_distance = 0 # 下一步覆盖最远距离下标 + + for i in range(len(nums)): + next_distance = max(nums[i] + i, next_distance) # 更新下一步覆盖最远距离下标 + if i == cur_distance: # 遇到当前覆盖最远距离下标 + ans += 1 # 需要走下一步 + cur_distance = next_distance # 更新当前覆盖最远距离下标(相当于加油了) + if next_distance >= len(nums) - 1: # 当前覆盖最远距离达到数组末尾,不用再做ans++操作,直接结束 + break + + return ans + ``` +贪心(版本二) ```python -# 动态规划做法 +class Solution: + def jump(self, nums): + cur_distance = 0 # 当前覆盖的最远距离下标 + ans = 0 # 记录走的最大步数 + next_distance = 0 # 下一步覆盖的最远距离下标 + + for i in range(len(nums) - 1): # 注意这里是小于len(nums) - 1,这是关键所在 + next_distance = max(nums[i] + i, next_distance) # 更新下一步覆盖的最远距离下标 + if i == cur_distance: # 遇到当前覆盖的最远距离下标 + cur_distance = next_distance # 更新当前覆盖的最远距离下标 + ans += 1 + + return ans + +``` +贪心(版本三) 类似‘55-跳跃游戏’写法 + +```python +class Solution: + def jump(self, nums) -> int: + if len(nums)==1: # 如果数组只有一个元素,不需要跳跃,步数为0 + return 0 + + i = 0 # 当前位置 + count = 0 # 步数计数器 + cover = 0 # 当前能够覆盖的最远距离 + + while i <= cover: # 当前位置小于等于当前能够覆盖的最远距离时循环 + for i in range(i, cover+1): # 遍历从当前位置到当前能够覆盖的最远距离之间的所有位置 + cover = max(nums[i]+i, cover) # 更新当前能够覆盖的最远距离 + if cover >= len(nums)-1: # 如果当前能够覆盖的最远距离达到或超过数组的最后一个位置,直接返回步数+1 + return count+1 + count += 1 # 每一轮遍历结束后,步数+1 + + +``` +动态规划 +```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 Date: Thu, 1 Jun 2023 00:45:16 -0500 Subject: [PATCH 03/10] =?UTF-8?q?Update=201005.K=E6=AC=A1=E5=8F=96?= =?UTF-8?q?=E5=8F=8D=E5=90=8E=E6=9C=80=E5=A4=A7=E5=8C=96=E7=9A=84=E6=95=B0?= =?UTF-8?q?=E7=BB=84=E5=92=8C.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../1005.K次取反后最大化的数组和.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/problems/1005.K次取反后最大化的数组和.md b/problems/1005.K次取反后最大化的数组和.md index 27a575c7..343bef04 100644 --- a/problems/1005.K次取反后最大化的数组和.md +++ b/problems/1005.K次取反后最大化的数组和.md @@ -155,17 +155,23 @@ class Solution { ``` ### Python +贪心 ```python class Solution: def largestSumAfterKNegations(self, A: List[int], K: int) -> int: - A = sorted(A, key=abs, reverse=True) # 将A按绝对值从大到小排列 - for i in range(len(A)): - if K > 0 and A[i] < 0: + A.sort(key=lambda x: abs(x), reverse=True) # 第一步:按照绝对值降序排序数组A + + for i in range(len(A)): # 第二步:执行K次取反操作 + if A[i] < 0 and K > 0: A[i] *= -1 K -= 1 - if K > 0: - A[-1] *= (-1)**K #取A最后一个数只需要写-1 - return sum(A) + + if K % 2 == 1: # 第三步:如果K还有剩余次数,将绝对值最小的元素取反 + A[-1] *= -1 + + result = sum(A) # 第四步:计算数组A的元素和 + return result + ``` ### Go From 648b0d2edc8cbf6c46b673f54ef610ba0524d5e3 Mon Sep 17 00:00:00 2001 From: jianghongcheng <35664721+jianghongcheng@users.noreply.github.com> Date: Thu, 1 Jun 2023 01:03:49 -0500 Subject: [PATCH 04/10] =?UTF-8?q?Update=200134.=E5=8A=A0=E6=B2=B9=E7=AB=99?= =?UTF-8?q?.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0134.加油站.md | 90 +++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/problems/0134.加油站.md b/problems/0134.加油站.md index f432bf0b..ad9acfbc 100644 --- a/problems/0134.加油站.md +++ b/problems/0134.加油站.md @@ -249,44 +249,74 @@ class Solution { ``` ### Python +暴力法 ```python -# 解法1 -class Solution: - def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int: - n = len(gas) - cur_sum = 0 - min_sum = float('inf') - - for i in range(n): - cur_sum += gas[i] - cost[i] - min_sum = min(min_sum, cur_sum) - - if cur_sum < 0: return -1 - if min_sum >= 0: return 0 - - for j in range(n - 1, 0, -1): - min_sum += gas[j] - cost[j] - if min_sum >= 0: - return j - - return -1 -``` -```python -# 解法2 class Solution: def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int: - start = 0 - curSum = 0 - totalSum = 0 + for i in range(len(cost)): + rest = gas[i] - cost[i] # 记录剩余油量 + index = (i + 1) % len(cost) # 下一个加油站的索引 + + while rest > 0 and index != i: # 模拟以i为起点行驶一圈(如果有rest==0,那么答案就不唯一了) + rest += gas[index] - cost[index] # 更新剩余油量 + index = (index + 1) % len(cost) # 更新下一个加油站的索引 + + if rest >= 0 and index == i: # 如果以i为起点跑一圈,剩余油量>=0,并且回到起始位置 + return i # 返回起始位置i + + return -1 # 所有起始位置都无法环绕一圈,返回-1 + +``` +贪心(版本一) +```python +class Solution: + def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int: + curSum = 0 # 当前累计的剩余油量 + minFuel = float('inf') # 从起点出发,油箱里的油量最小值 + + for i in range(len(gas)): + rest = gas[i] - cost[i] + curSum += rest + if curSum < minFuel: + minFuel = curSum + + if curSum < 0: + return -1 # 情况1:整个行程的总消耗大于总供给,无法完成一圈 + + if minFuel >= 0: + return 0 # 情况2:从起点出发到任何一个加油站时油箱的剩余油量都不会小于0,可以从起点出发完成一圈 + + for i in range(len(gas) - 1, -1, -1): + rest = gas[i] - cost[i] + minFuel += rest + if minFuel >= 0: + return i # 情况3:找到一个位置使得从该位置出发油箱的剩余油量不会小于0,返回该位置的索引 + + return -1 # 无法完成一圈 + +``` +贪心(版本二) +```python +class Solution: + def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int: + curSum = 0 # 当前累计的剩余油量 + totalSum = 0 # 总剩余油量 + start = 0 # 起始位置 + for i in range(len(gas)): curSum += gas[i] - cost[i] totalSum += gas[i] - cost[i] - if curSum < 0: - curSum = 0 - start = i + 1 - if totalSum < 0: return -1 + + if curSum < 0: # 当前累计剩余油量curSum小于0 + start = i + 1 # 起始位置更新为i+1 + curSum = 0 # curSum重新从0开始累计 + + if totalSum < 0: + return -1 # 总剩余油量totalSum小于0,说明无法环绕一圈 return start + + ``` ### Go From cfb10d2e2a24324a319fec0986dee0ef465394fc Mon Sep 17 00:00:00 2001 From: jianghongcheng <35664721+jianghongcheng@users.noreply.github.com> Date: Thu, 1 Jun 2023 01:35:04 -0500 Subject: [PATCH 05/10] =?UTF-8?q?Update=200135.=E5=88=86=E5=8F=91=E7=B3=96?= =?UTF-8?q?=E6=9E=9C.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0135.分发糖果.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/problems/0135.分发糖果.md b/problems/0135.分发糖果.md index 1ba1563f..cf3ccc8e 100644 --- a/problems/0135.分发糖果.md +++ b/problems/0135.分发糖果.md @@ -178,13 +178,21 @@ class Solution { class Solution: def candy(self, ratings: List[int]) -> int: candyVec = [1] * len(ratings) + + # 从前向后遍历,处理右侧比左侧评分高的情况 for i in range(1, len(ratings)): if ratings[i] > ratings[i - 1]: candyVec[i] = candyVec[i - 1] + 1 - for j in range(len(ratings) - 2, -1, -1): - if ratings[j] > ratings[j + 1]: - candyVec[j] = max(candyVec[j], candyVec[j + 1] + 1) - return sum(candyVec) + + # 从后向前遍历,处理左侧比右侧评分高的情况 + for i in range(len(ratings) - 2, -1, -1): + if ratings[i] > ratings[i + 1]: + candyVec[i] = max(candyVec[i], candyVec[i + 1] + 1) + + # 统计结果 + result = sum(candyVec) + return result + ``` ### Go From ba3c7ec19b6b2ad3f95f35ae55f25b2459d710b3 Mon Sep 17 00:00:00 2001 From: jianghongcheng <35664721+jianghongcheng@users.noreply.github.com> Date: Thu, 1 Jun 2023 01:37:41 -0500 Subject: [PATCH 06/10] =?UTF-8?q?Update=200860.=E6=9F=A0=E6=AA=AC=E6=B0=B4?= =?UTF-8?q?=E6=89=BE=E9=9B=B6.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0860.柠檬水找零.md | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/problems/0860.柠檬水找零.md b/problems/0860.柠檬水找零.md index d96e0879..5046df12 100644 --- a/problems/0860.柠檬水找零.md +++ b/problems/0860.柠檬水找零.md @@ -164,24 +164,39 @@ class Solution { ```python class Solution: def lemonadeChange(self, bills: List[int]) -> bool: - five, ten = 0, 0 + five = 0 + ten = 0 + twenty = 0 + for bill in bills: + # 情况一:收到5美元 if bill == 5: five += 1 - elif bill == 10: - if five < 1: return False - five -= 1 + + # 情况二:收到10美元 + if bill == 10: + if five <= 0: + return False ten += 1 - else: - if ten > 0 and five > 0: - ten -= 1 + five -= 1 + + # 情况三:收到20美元 + if bill == 20: + # 先尝试使用10美元和5美元找零 + if five > 0 and ten > 0: five -= 1 - elif five > 2: + ten -= 1 + #twenty += 1 + # 如果无法使用10美元找零,则尝试使用三张5美元找零 + elif five >= 3: five -= 3 + #twenty += 1 else: return False + return True + ``` ### Go From cd4d54616200a53d9a22fbd919edf905ad1d4dd1 Mon Sep 17 00:00:00 2001 From: jianghongcheng <35664721+jianghongcheng@users.noreply.github.com> Date: Thu, 1 Jun 2023 02:16:29 -0500 Subject: [PATCH 07/10] =?UTF-8?q?Update=200435.=E6=97=A0=E9=87=8D=E5=8F=A0?= =?UTF-8?q?=E5=8C=BA=E9=97=B4.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0435.无重叠区间.md | 41 +++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/problems/0435.无重叠区间.md b/problems/0435.无重叠区间.md index 37ef819d..61f42d42 100644 --- a/problems/0435.无重叠区间.md +++ b/problems/0435.无重叠区间.md @@ -248,20 +248,45 @@ class Solution { ``` ### Python +贪心 基于左边界 ```python class Solution: def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int: - if len(intervals) == 0: return 0 - intervals.sort(key=lambda x: x[1]) - count = 1 # 记录非交叉区间的个数 - end = intervals[0][1] # 记录区间分割点 + if not intervals: + return 0 + + intervals.sort(key=lambda x: x[0]) # 按照左边界升序排序 + count = 0 # 记录重叠区间数量 + for i in range(1, len(intervals)): - if end <= intervals[i][0]: + if intervals[i][0] < intervals[i - 1][1]: # 存在重叠区间 + intervals[i][1] = min(intervals[i - 1][1], intervals[i][1]) # 更新重叠区间的右边界 count += 1 - end = intervals[i][1] - return len(intervals) - count -``` + + return count +``` +贪心 基于左边界 把452.用最少数量的箭引爆气球代码稍做修改 +```python +class Solution: + def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int: + if not intervals: + return 0 + + intervals.sort(key=lambda x: x[0]) # 按照左边界升序排序 + + result = 1 # 不重叠区间数量,初始化为1,因为至少有一个不重叠的区间 + + for i in range(1, len(intervals)): + if intervals[i][0] >= intervals[i - 1][1]: # 没有重叠 + result += 1 + else: # 重叠情况 + intervals[i][1] = min(intervals[i - 1][1], intervals[i][1]) # 更新重叠区间的右边界 + + return len(intervals) - result + + +``` ### Go ```go func eraseOverlapIntervals(intervals [][]int) int { From 458f94b8b94b6e9252dc23dc11f6627a4272e2b8 Mon Sep 17 00:00:00 2001 From: jianghongcheng <35664721+jianghongcheng@users.noreply.github.com> Date: Thu, 1 Jun 2023 02:26:34 -0500 Subject: [PATCH 08/10] =?UTF-8?q?Update=200763.=E5=88=92=E5=88=86=E5=AD=97?= =?UTF-8?q?=E6=AF=8D=E5=8C=BA=E9=97=B4.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0763.划分字母区间.md | 111 +++++++++++----------------- 1 file changed, 42 insertions(+), 69 deletions(-) diff --git a/problems/0763.划分字母区间.md b/problems/0763.划分字母区间.md index fbcafdc8..158f76d6 100644 --- a/problems/0763.划分字母区间.md +++ b/problems/0763.划分字母区间.md @@ -231,83 +231,56 @@ class Solution{ ``` ### Python +贪心(版本一) ```python class Solution: def partitionLabels(self, s: str) -> List[int]: - hash = [0] * 26 - for i in range(len(s)): - hash[ord(s[i]) - ord('a')] = i + last_occurrence = {} # 存储每个字符最后出现的位置 + for i, ch in enumerate(s): + last_occurrence[ch] = i + result = [] - left = 0 - right = 0 - for i in range(len(s)): - right = max(right, hash[ord(s[i]) - ord('a')]) - if i == right: - result.append(right - left + 1) - left = i + 1 + start = 0 + end = 0 + for i, ch in enumerate(s): + end = max(end, last_occurrence[ch]) # 找到当前字符出现的最远位置 + if i == end: # 如果当前位置是最远位置,表示可以分割出一个区间 + result.append(end - start + 1) + start = i + 1 + return result - -# 解法二(不相交区间法) + +``` +贪心(版本二)与452.用最少数量的箭引爆气球 (opens new window)、435.无重叠区间 (opens new window)相同的思路。 +```python 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] + def countLabels(self, s): + # 初始化一个长度为26的区间列表,初始值为负无穷 + hash = [[float('-inf'), float('-inf')] for _ in range(26)] + hash_filter = [] + 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 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) + if hash[i][0] != float('-inf'): + hash_filter.append(hash[i]) + return hash_filter + + def partitionLabels(self, s): + res = [] + hash = self.countLabels(s) + hash.sort(key=lambda x: x[0]) # 按左边界从小到大排序 + rightBoard = hash[0][1] # 记录最大右边界 + leftBoard = 0 + for i in range(1, len(hash)): + if hash[i][0] > rightBoard: # 出现分割点 + res.append(rightBoard - leftBoard + 1) + leftBoard = hash[i][0] + rightBoard = max(rightBoard, hash[i][1]) + res.append(rightBoard - leftBoard + 1) # 最右端 return res - -# 解法三:区间合并法 (结合下一题 56. Merge Intervals 的写法) -class Solution: # - def partitionLabels(self, s: str) -> List[int]: - aaa = list(set(s)) - #aaa.sort() - bbb = list(s) - ccc = [] - for i in reversed(bbb): - ccc.append(i) - intervals = [] - for i in range(len(aaa)): - intervals.append([bbb.index(aaa[i]),len(bbb)-ccc.index(aaa[i])-1]) - # 先求出各个字母的存在区间,之后利用区间合并方法得出所有不相邻的最大区间。 - intervals.sort(key = lambda x:x[0]) - newinterval = [] - left, right = intervals[0][0], intervals[0][1] - for i in range(1,len(intervals)): - if intervals[i][0] in range(left, right+1): - right = max(intervals[i][1],intervals[i-1][1],right) - left = min(intervals[i-1][0],left) - else: - newinterval.append(right-left+1) - left = intervals[i][0] - right = intervals[i][1] - newinterval.append(right-left+1) - return newinterval + ``` ### Go From 352b51d550a6edcc9b6355b8773b91d4f69cb507 Mon Sep 17 00:00:00 2001 From: jianghongcheng <35664721+jianghongcheng@users.noreply.github.com> Date: Thu, 1 Jun 2023 02:36:11 -0500 Subject: [PATCH 09/10] =?UTF-8?q?Update=200056.=E5=90=88=E5=B9=B6=E5=8C=BA?= =?UTF-8?q?=E9=97=B4.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0056.合并区间.md | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/problems/0056.合并区间.md b/problems/0056.合并区间.md index 952d32af..ead2fb75 100644 --- a/problems/0056.合并区间.md +++ b/problems/0056.合并区间.md @@ -141,18 +141,24 @@ class Solution { ### Python ```python class Solution: - def merge(self, intervals: List[List[int]]) -> List[List[int]]: - if len(intervals) == 0: return intervals - intervals.sort(key=lambda x: x[0]) + def merge(self, intervals): result = [] - result.append(intervals[0]) + if len(intervals) == 0: + return result # 区间集合为空直接返回 + + intervals.sort(key=lambda x: x[0]) # 按照区间的左边界进行排序 + + result.append(intervals[0]) # 第一个区间可以直接放入结果集中 + for i in range(1, len(intervals)): - last = result[-1] - if last[1] >= intervals[i][0]: - result[-1] = [last[0], max(last[1], intervals[i][1])] + if result[-1][1] >= intervals[i][0]: # 发现重叠区间 + # 合并区间,只需要更新结果集最后一个区间的右边界,因为根据排序,左边界已经是最小的 + result[-1][1] = max(result[-1][1], intervals[i][1]) else: - result.append(intervals[i]) + result.append(intervals[i]) # 区间不重叠 + return result + ``` ### Go From 41dd31d826218bef8b25890b9dc31744fc3b5dd7 Mon Sep 17 00:00:00 2001 From: jianghongcheng <35664721+jianghongcheng@users.noreply.github.com> Date: Thu, 1 Jun 2023 02:54:22 -0500 Subject: [PATCH 10/10] =?UTF-8?q?Update=200738.=E5=8D=95=E8=B0=83=E9=80=92?= =?UTF-8?q?=E5=A2=9E=E7=9A=84=E6=95=B0=E5=AD=97.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0738.单调递增的数字.md | 109 +++++++++++++++++++++++-- 1 file changed, 101 insertions(+), 8 deletions(-) diff --git a/problems/0738.单调递增的数字.md b/problems/0738.单调递增的数字.md index 1cf8a0a6..d88ebbb0 100644 --- a/problems/0738.单调递增的数字.md +++ b/problems/0738.单调递增的数字.md @@ -164,17 +164,110 @@ class Solution { ### Python: +暴力 ```python class Solution: - def monotoneIncreasingDigits(self, n: int) -> int: - a = list(str(n)) - for i in range(len(a)-1,0,-1): - if int(a[i]) < int(a[i-1]): - a[i-1] = str(int(a[i-1]) - 1) - a[i:] = '9' * (len(a) - i) #python不需要设置flag值,直接按长度给9就好了 - return int("".join(a)) -``` + def checkNum(self, num): + max_digit = 10 + while num: + digit = num % 10 + if max_digit >= digit: + max_digit = digit + else: + return False + num //= 10 + return True + def monotoneIncreasingDigits(self, N): + for i in range(N, 0, -1): + if self.checkNum(i): + return i + return 0 + +``` +贪心(版本一) +```python +class Solution: + def monotoneIncreasingDigits(self, N: int) -> int: + # 将整数转换为字符串 + strNum = str(N) + # flag用来标记赋值9从哪里开始 + # 设置为字符串长度,为了防止第二个for循环在flag没有被赋值的情况下执行 + flag = len(strNum) + + # 从右往左遍历字符串 + for i in range(len(strNum) - 1, 0, -1): + # 如果当前字符比前一个字符小,说明需要修改前一个字符 + if strNum[i - 1] > strNum[i]: + flag = i # 更新flag的值,记录需要修改的位置 + # 将前一个字符减1,以保证递增性质 + strNum = strNum[:i - 1] + str(int(strNum[i - 1]) - 1) + strNum[i:] + + # 将flag位置及之后的字符都修改为9,以保证最大的递增数字 + for i in range(flag, len(strNum)): + strNum = strNum[:i] + '9' + strNum[i + 1:] + + # 将最终的字符串转换回整数并返回 + return int(strNum) + +``` +贪心(版本二) +```python +class Solution: + def monotoneIncreasingDigits(self, N: int) -> int: + # 将整数转换为字符串 + strNum = list(str(N)) + + # 从右往左遍历字符串 + for i in range(len(strNum) - 1, 0, -1): + # 如果当前字符比前一个字符小,说明需要修改前一个字符 + if strNum[i - 1] > strNum[i]: + strNum[i - 1] = str(int(strNum[i - 1]) - 1) # 将前一个字符减1 + # 将修改位置后面的字符都设置为9,因为修改前一个字符可能破坏了递增性质 + for j in range(i, len(strNum)): + strNum[j] = '9' + + # 将列表转换为字符串,并将字符串转换为整数并返回 + return int(''.join(strNum)) + + +``` +贪心(版本三) + +```python +class Solution: + def monotoneIncreasingDigits(self, N: int) -> int: + # 将整数转换为字符串 + strNum = list(str(N)) + + # 从右往左遍历字符串 + for i in range(len(strNum) - 1, 0, -1): + # 如果当前字符比前一个字符小,说明需要修改前一个字符 + if strNum[i - 1] > strNum[i]: + strNum[i - 1] = str(int(strNum[i - 1]) - 1) # 将前一个字符减1 + # 将修改位置后面的字符都设置为9,因为修改前一个字符可能破坏了递增性质 + strNum[i:] = '9' * (len(strNum) - i) + + # 将列表转换为字符串,并将字符串转换为整数并返回 + return int(''.join(strNum)) + +``` +贪心(版本四)精简 + +```python +class Solution: + def monotoneIncreasingDigits(self, N: int) -> int: + strNum = str(N) + for i in range(len(strNum) - 1, 0, -1): + # 如果当前字符比前一个字符小,说明需要修改前一个字符 + if strNum[i - 1] > strNum[i]: + # 将前一个字符减1,以保证递增性质 + # 使用字符串切片操作将修改后的前面部分与后面部分进行拼接 + strNum = strNum[:i - 1] + str(int(strNum[i - 1]) - 1) + '9' * (len(strNum) - i) + return int(strNum) + + +``` ### Go ```go func monotoneIncreasingDigits(N int) int {