[NeetCode 150] Non-overlapping Intervals

Non-overlapping Intervals

Given an array of intervals intervals where intervals[i] = [start_i, end_i], return the minimum number of intervals you need to remove to make the rest of the intervals non-overlapping.

Note: Intervals are non-overlapping even if they have a common point. For example, [1, 3] and [2, 4] are overlapping, but [1, 2] and [2, 3] are non-overlapping.

Example 1:

Input: intervals = [[1,2],[2,4],[1,4]]

Output: 1

Explanation: After [1,4] is removed, the rest of the intervals are non-overlapping.

Example 2:

Input: intervals = [[1,2],[2,4]]

Output: 0

Constraints:

1 <= intervals.length <= 1000
intervals[i].length == 2
-50000 <= starti < endi <= 50000

Solution

A method in DP is sorting the intervals by their right endpoints. Let d p [ i ] dp[i] dp[i] denotes the maximum number of non-overlapping intervals for left i i i intervals. And one interval can get a transfer from the last non-overlapping interval in front of it. We can use binary search to find one interval’s last non-overlapping interval in front. The time complexity is O ( n log ⁡ n ) O(n\log n) O(nlogn).

However, after we sort the intervals by left endpoint, where the time complexity is O ( n log ⁡ n ) O(n\log n) O(nlogn), we can get the answer in O ( n ) O(n) O(n). In a greedy strategy, when we go through the intervals in ascending order, we will keep intervals with the least right endpoint, so that there will be more chances to put more intervals. So, when facing overlapping, we will keep the one will smaller right endpoint and discard the other one. Because the intervals are sorted in left endpoint ascending order, we don’t have to worry the former left endpoints and just focusing on former largest right endpoints and current endpoints.

Code

Binary search

class Solution:
    def search(self, intervals, left):
        le = 0
        ri = len(intervals)-1
        pos = -1
        while le <= ri:
            mid = (le+ri)//2
            if intervals[mid][1] <= left:
                pos = mid
                le = mid+1
            else:
                ri = mid-1
        return pos

    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        intervals += [[-50001, -50001], [50001, 50001]]
        intervals = sorted(intervals, key=lambda x:(x[1], x[0]))
        print(intervals)

        dp = [0]*len(intervals)
        for i in range(1, len(dp)-1):
            former = self.search(intervals, intervals[i][0])
            dp[i] = max(dp[i-1], dp[former]+1)
        
        print(dp)

        return len(intervals) - dp[-2] - 2
        

O ( n ) O(n) O(n) after sorting

class Solution:
    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        intervals.sort()
        res = 0
        prevEnd = intervals[0][1]
        
        for start, end in intervals[1:]:
            if start >= prevEnd:
                prevEnd = end
            else:
                res += 1
                prevEnd = min(end, prevEnd)
        return res

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值