1.452用最少数量的箭引爆气球
只按右端点排序(左端点大小无所谓),射在右端点,尽可能多射到气球
class Solution:
def findMinArrowShots(self, points: List[List[int]]) -> int:
points.sort(key = lambda x :x[1])
arrows = 1
position = points[0][1]
for point in points[1:]:
if point[0] > position:
arrows += 1
position = point[1]
return arrows
2.435. 无重叠区间
和上一题一样,这俩题本质是一道题,也是只按右端点排序,重叠则删除右端点大的区间,这样可以尽可能避免重叠。
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
intervals.sort(key = lambda x :x[1])
n = len(intervals)
remove = 0
curr_end = intervals[0][1]
for i in range(1,n):
if intervals[i][0] < curr_end:
remove += 1
else:
curr_end = intervals[i][1]
return remove
3.763. 划分字母区间
缝缝补补才写出来,我的方法太过于复杂
构建字典 → 提取区间 → 排序 → 合并区间
class Solution:
def partitionLabels(self, s: str) -> List[int]:
res = []
char_intervals = defaultdict(list)
for i,ch in enumerate(s):
if ch not in char_intervals:
char_intervals[ch] = [i,i]
char_intervals[ch][1] = i
intervals = list(char_intervals.values())
intervals.sort(key = lambda x: x[0])
start = 0
curr_end = intervals[0][1]
for interval in intervals:
if interval[0] > curr_end:
res.append(curr_end-start+1 )
curr_end = interval[1]
start = interval[0]
else:
curr_end = max(curr_end, interval[1])
res.append(curr_end-start+1)
return res
优化:
只记录字符最后一次出现的位置,遍历字符,扩展end边界。
class Solution:
def partitionLabels(self, s: str) -> List[int]:
last_index = {ch: i for i, ch in enumerate(s)}
res = []
start = end = 0
for i, ch in enumerate(s):
end = max(end, last_index[ch])
if i == end:
res.append(end - start + 1)
start = i + 1
return res
4.56. 合并区间
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort(key = lambda x:x[0])
res = [intervals[0]]
for interval in intervals[1:]:
if interval[0] > res[-1][1]:
res.append(interval)
else:
start,end = res.pop()
res.append([start, max(interval[1],end)])
return res
优化:else部分,可以直接修改,不用pop
res[-1][1] = max(res[-1][1],interval[1])
6.738. 单调递增的数字
我想的是从左往右扫描,需要回溯去找mark的位置,逻辑比较复杂
- str不能直接修改,转换为list修改
- 字符比较大小时通过ASCII码比较,这里是单个字符,可以直接比较大小 (‘1’与‘5’)
- 处理重复数字用while,这里回头往前探测
- 找到mark,将数字减一,注意字符与数字的转换
- 后面的字符全改为‘9’
- 字符拼接并转为int
- int可以直接处理0开头的字符串,‘019’-->19
class Solution:
def monotoneIncreasingDigits(self, n: int) -> int:
#找到第一个下降的数字
#找到它前面的数字(可能有重复)-1,后面全为9
#字符与数字的转换
digits = list(str(n)) #['1','5','0']
n = len(digits)
mark = None
for i in range(n):
if i > 0 and digits[i] < digits[i-1]:
mark = i-1
while mark > 0 and digits[mark-1] == digits[mark]:
mark -= 1
break
if mark is not None:
digits[mark] = str(int(digits[mark]) - 1)
for i in range(mark+1, n):
digits[i] = '9'
return int(''.join(digits))
优化:从右往左扫描,不用回溯逻辑清晰多了。老是忘记初始化mark。。
class Solution:
def monotoneIncreasingDigits(self, n: int) -> int:
digits = list(str(n))
n = len(digits)
mark = n #随便一个不存在的位置
for i in range(n-1, 0,-1):#[n-1,1]
if digits[i-1] > digits[i]:
digits[i-1] = str(int(digits[i-1]) -1)
mark = i-1
for i in range(mark+1, n):
digits[i] = '9'
return int(''.join(digits))

3万+

被折叠的 条评论
为什么被折叠?



