Leetcode 435.无重叠区间
题目:435.无重叠区间
初始思路
代码
var eraseOverlapIntervals = function (intervals) {
// 按照右边界从小到大排序
intervals.sort((a, b) => {
return a[1] - b[1]
})
// 记录非交叉区间的个数
let count = 1
// 记录区间分割点
let end = intervals[0][1]
for (let i = 1; i < intervals.length; i++){
let temp = intervals[i]
if (temp[0] >= end) {
// 如果区间不交叉更新分割点
end = temp[1]
count++
}
}
// 区间总数减去非交叉区间就是需要移除的区间个数
return intervals.length - count
};
感想
- 按照右边界排序,就要从左向右遍历,因为右边界越小越好,只要右边界越小,留给下一个区间的空间就越大,所以从左向右遍历,优先选右边界小的。
- 按照右边界排序,从左向右记录非交叉区间的个数。最后用区间总数减去非交叉区间的个数就是需要移除的区间个数了。
Leetcode 763.划分字母区间
题目:763.划分字母区间
初始思路
找最远下标可以用lastIndexOf,不停遍历更新也可以。
代码
var partitionLabels = function (s) {
let hash = {}
for (let i = 0; i < s.length; i++){
// 获得最远下标
hash[s[i]] = i
}
let res = []
let left = 0
let right = 0
for (let i = 0; i < s.length; i++){
// 当前右区间和最远下标作比较
right = Math.max(right, hash[s[i]])
// 如果右区间到了最远坐标就可以分割了
if (right === i) {
// 加入这段区间的长度
res.push(right - left + 1)
// 开始下一段区间的寻找
left = i + 1
}
}
return res
};
感想
- 在遍历的过程中相当于是要找每一个字母的边界,如果找到之前遍历过的所有字母的最远边界,说明这个边界就是分割点了。此时前面出现过所有字母,最远也就到这个边界了。
Leetcode 56.合并区间
题目:56.合并区间
初始思路
代码
var merge = function (intervals) {
// 按照左边界从小到大排序
intervals.sort((a, b) => {
return a[0] - b[0]
})
let prev = intervals[0]
let res = []
for (let i = 0; i < intervals.length; i++){
let temp = intervals[i]
if (temp[0] > prev[1]) {
// 如果区间不重叠,直接把前一个区间加进去
res.push(prev)
// 进入下一个区间开始比较
prev = temp
} else {
// 如果重叠的话,右区间取两者最大值
prev[1] = Math.max(temp[1], prev[1])
}
}
// 加入最后一个区间
res.push(prev)
return res
};
感想
- 按照左边界排序,排序之后局部最优:每次合并都取最大的右边界,这样就可以合并更多的区间了,整体最优:合并所有重叠的区间。
- 按照左边界从小到大排序之后,如果 intervals[i][0] < intervals[i - 1][1] 即intervals[i]左边界 < intervals[i - 1]右边界,则一定有重复,因为intervals[i]的左边界一定是大于等于intervals[i - 1]的左边界。
- 即:intervals[i]的左边界在intervals[i - 1]左边界和右边界的范围内,那么一定有重复!