无重叠区间-435
sl1673495 opened this issue · comments
ssh commented
给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。
注意:
可以认为区间的终点总是大于它的起点。
区间 [1,2]
和 [2,3]
的边界相互“接触”,但没有相互重叠。
示例 1:
输入: [ [1,2], [2,3], [3,4], [1,3] ]
输出: 1
解释: 移除 [1,3] 后,剩下的区间没有重叠。
示例 2:
输入: [ [1,2], [1,2], [1,2] ]
输出: 2
解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠。
示例 3:
输入: [ [1,2], [2,3] ]
输出: 0
解释: 你不需要移除任何区间,因为它们已经是无重叠的了。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/non-overlapping-intervals
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
本题可以转化成最长上升子序列-300相同的问题。
先把区间数组按照每个数组的开头项排序,然后用 dp[i]
表示从 [0, i] 能构成的最长的无重叠区间的个数,利用上升子序列的同样思路去求解即可。对于每个区间intervals[i]
,都从 0 ~ j
去逐个遍历之前的项,一旦发现 i.start >= j.end
说明这两者构成非重叠区间,那么就把 max
值尝试更新为 dp[j] + 1
。
最后找出所有 dp 项中的最大值,也就是最长的非重叠区间长度,用区间的总长度减去这个最长长度,得出的就是需要移除掉的数组长度。
/**
* @param {number[][]} intervals
* @return {number}
*/
let eraseOverlapIntervals = function (intervals) {
let n = intervals.length
if (!n) {
return 0
}
// 按照起始点排序
intervals.sort((a, b) => a[0] - b[0])
// dp[i] 表示从 [0, i] 能构成的最长的无重叠区间的个数
let dp = []
dp[0] = 1
for (let i = 1; i < n; i++) {
let max = 1
let [curStart] = intervals[i]
for (let j = 0; j < i; j++) {
let [prevStart, prevEnd] = intervals[j]
if (prevEnd <= curStart) {
max = Math.max(max, dp[j] + 1)
}
}
dp[i] = max
}
return n - Math.max(...dp)
}