mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-07 07:35:35 +08:00
@ -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<len(nums): result[i+j]=min(result[i+j],result[i]+1)
|
||||
#print(result) #打印数组
|
||||
return result[-1]
|
||||
result = [10**4+1] * len(nums) # 初始化结果数组,初始值为一个较大的数
|
||||
result[0] = 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) # 更新到达下一跳位置的最小步数
|
||||
|
||||
return result[-1] # 返回到达最后一个位置的最小步数
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
@ -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
|
||||
|
@ -140,18 +140,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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -131,17 +131,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
|
||||
|
Reference in New Issue
Block a user