-
435无重叠区间
- 代码随想录 (programmercarl.com)
-
第一印象
- 排序是必要的,难点在于如何统计同时与多个区间重叠的区间。
-
讲解观后感
- 排序的方式选择用左边界还是有边界进行排序,决定了统计重叠区间还是非重叠区间更合适。在排序左边界的方法中,统计的方法核心逻辑是判断最小右边界与当前区间的重叠关系;排序右边界的方法则是离开一组重叠区间任意一个的右边即可。
-
解题代码
- 排序右边界
-
func eraseOverlapIntervals(intervals [][]int) int {
sort.Slice(intervals, func(i, j int) bool {
return intervals[i][1] < intervals[j][1]
})
unOl := 1
end := intervals[0][1]
for i := 1; i < len(intervals); i++ {
if end <= intervals[i][0] {
end = intervals[i][1]
unOl++
}
}
return len(intervals) - unOl
}
- 排序左边界
-
func eraseOverlapIntervals(intervals [][]int) int {
sort.Slice(intervals, func(i, j int) bool {
return intervals[i][0] < intervals[j][0]
})
res := 0
end := intervals[0][1]
for i := 1; i < len(intervals); i++ {
if intervals[i][0] < end {
res++
end = min(end, intervals[i][1])
} else {
end = intervals[i][1]
}
}
return res
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
- 打气球改写法
-
func eraseOverlapIntervals(intervals [][]int) int {
sort.Slice(intervals, func(i, j int) bool {
return intervals[i][1] < intervals[j][1]
})
res := 1
for i := 1; i < len(intervals); i++ {
if intervals[i][0] >= intervals[i-1][1] {
res++
} else {
intervals[i][1] = min(intervals[i - 1][1], intervals[i][1])
}
}
return len(intervals) - res
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
-
763划分字母区间
- 代码随想录 (programmercarl.com)
-
第一印象
- 感觉可以一次判断每个字母在前面有没有出现过,没有出现过片段则加一,出现过则根据位置重置片段统计数。但是判断出现的存储逻辑很难构建。
-
讲解观后感
- 统计数字最远出现的下标,实在是巧妙的方法。如果找到之前遍历过的所有字母的最远边界,说明这个边界就是分割点了。
-
解题代码
-
func partitionLabels(s string) []int {
var res []int;
var marks [26]int;
left, right :=0, 0;
for i := 0; i < len(s); i++ {
marks[s[i] - 'a'] = i;
}
for i := 0; i < len(s); i++ {
right = max(right, marks[s[i] - 'a']);
if i == right {
res = append(res, right - left + 1);
left = i + 1;
}
}
return res;
}
func max(a, b int) int {
if a < b {
a = b;
}
return a;
}
-
56合并区间
- 代码随想录 (programmercarl.com)
-
第一印象
- 同时维护前一个区间和当前区间,判定是否重叠,如果重叠则更新当前区间的范围,删除前一个区间,并将当前区间赋值到上一个区间值。
-
讲解观后感
- 重叠区间的题目的判定都是一样的逻辑,先通过左边界或者右边界进行排序,然后再构建判断和处理逻辑。
- 本题再通过双指针的方式更新边界,就可以省略每次更新新区间的过程,而是没有重叠的时候再压入结果集。
-
解题代码
- 左边界排序
-
func merge(intervals [][]int) [][]int {
sort.Slice(intervals, func(i, j int) bool {
return intervals[i][0] < intervals[j][0]
})
res := make([][]int, 0, len(intervals))
left, right := intervals[0][0], intervals[0][1]
for i := 1; i < len(intervals); i++ {
if right < intervals[i][0] {
res = append(res, []int{left, right})
left, right = intervals[i][0], intervals[i][1]
} else {
right = max(right, intervals[i][1])
}
}
res = append(res, []int{left, right}) // 将最后一个区间放入
return res
}
func max(a, b int) int {
if a > b {
return a
}
return b
}