今日题目:
435. 无重叠区间
763. 划分字母区间
56. 合并区间
今日总结
重叠区间的题目还是比较容易的,符合直觉。第一步先是考虑排序,要熟悉golang的sort.Slice写法。之后根据左右边界的大小讨论重叠与未重叠的情况,再进行内部的逻辑实现。这里的第二道题很有意思,值得研究。
435. 无重叠区间
要点
- 类似于之前的弓箭射气球,重叠区间的典型题目。
- 这道题既可以靠左排序也可以靠右排序。靠左排序就是找重叠区间靠右就是找无重叠区间。
- 一旦发生重叠就意味着需要删除一个区间,res++。这里面minRightBound的更新对应两种情况,一种是下一个区间的右边界小于当前minRightBound(即新区间很小,被旧区间覆盖着),另一种则是右边界大于当前minRightBound,此时不需要变。使用min函数可以省略if分支。
- 再加上未重叠的情况,这道题总共有三种情况。
代码:
func eraseOverlapIntervals(intervals [][]int) int {
res := 0
sort.Slice(intervals, func(i int, j int) bool{
return intervals[i][0] <= intervals[j][0]
})
minRightBound := intervals[0][1]
for i :=1;i<len(intervals);i++{
if minRightBound > intervals[i][0] {
res++
if intervals[i][1] < minRightBound {
minRightBound = intervals[i][1]
}
} else {
minRightBound = intervals[i][1]
}
}
return res
}
763. 划分字母区间
要点:
- 比较特殊的一道题目。一开始的想法是统计字母出现的次数,当所有遍历过的字母剩余次数归零时就分割一次字符串。想法应该没问题,不过实现起来太复杂了,放弃。
- 那么这道题的正确思路是先寻找每个字符最晚出现的位置。这意味着在右边不会再次出现这个字符。
- 当i等于遍历过的字符的最晚出现的位置,便进行一次分割。之前出现过的所有字符都不会在右边出现。所以这里right要取最大值。
func partitionLabels(s string) []int {
res := make([]int, 0)
hash:= make([]int, 26)
left, right := 0, 0
for i :=0;i<len(s);i++{
hash[s[i]-'a'] = i
}
for i :=0; i <len(s);i++{
right = max(right, hash[s[i]-'a'])
if i == right {
res = append(res, right - left + 1);
left = i + 1;
}
}
return res
}
func max(a int, b int) int{
if a>b{
return a
}
return b
}
56. 合并区间
要点:
- 类似于之前的无重叠区间,这里依然是先排序再找重叠区间。
- 这道题目的区别在于需要合并区间,那么只需要判断重叠时,将右边界替换为最右边界即可。
- 不重叠时,将之前的区间添加进结果。左边界前移,右边界也要替换为当前区间的右边界。
- 注意最后一个区间需要单独添加。
func merge(intervals [][]int) [][]int {
res := [][]int{}
sort.Slice(intervals, func(i int, j int) bool{
if intervals[i][0] == intervals[j][0] {
return intervals[i][1] < intervals[j][1]
}
return intervals[i][0] < intervals[j][0]
})
left, right := intervals[0][0], intervals[0][1]
for i:=1;i <len(intervals);i++{
if intervals[i][0] <= right {
right = max(intervals[i][1],right)
} else {
res = append(res, []int{left, right})
left = intervals[i][0]
right = intervals[i][1]
}
}
res = append(res, []int{left, right}) // 添加最后一个片段
return res
}
func max(a int, b int) int{
if a > b {
return a
}
return b
}
//查询是否重叠,一旦出现非重叠区域:
//将最左边和最大右边界区域合并