贪心 + 排序
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
if not intervals:
return 0
# sort intervals by start point
intervals.sort()
pre = intervals[0]
count = 0
for i in range(1, len(intervals)):
cur = intervals[i]
# there are 3 cases
# case 1: previous interval is NOT overlapping with current interval
# |__pre__| |__cur_|
# strategy: we can have both intervals in the candidate list
if self._is_not_overlap(pre, cur):
# print('not overlap')
pre = cur
# case 2: two intervals overlap, but current interval ends earlier
# |__________pre________|
# |____cur___|
# strategy: keep 'cur', and remove 'pre' from the candidate list
elif self._is_first_interval_shorter(cur, pre):
# print('case 2')
pre = cur
count += 1
# case 3: two intervals overlap, but previous interval ends earlier
# |____pre___|
# |______cur_____|
# GREEDY strategy: we always keep 'pre', and remove 'cur' interval
# because no matter what cases is the next interval after current, it's always better to keep previous interval
#
# case 3.1
# |__pre___|
# |__cur__| |__next__|
# strategy: either previous or current interval will work
#
# case 3.2
# |__pre_______| or |__pre__|
# |_____cur__________| |__cur____________|
# |__next__| |__next__|
# strategy: only previous interval has the chance to NOT overlap with next interval -> take 'pre'
#
# case 3.3
# |__pre___| or |__pre___|
# |__cur_______| |__cur_______|
# |__next_____| |__next____|
# strategy: only previous interval has the chance to NOT overlap with next interval -> take 'pre'
else:
# print('case 3')
count += 1
return count
# is first interval ends earlier than the second one?
def _is_first_interval_shorter(self, interval_first: List[int], interval_second: List[int]) -> bool:
interval_first_end = interval_first[1]
interval_second_end = interval_second[1]
return interval_first_end <= interval_second_end
# it's guaranteed that interval_1 will always start before interval_2
def _is_not_overlap(self, interval_1: List[int], interval_2: List[int]) -> bool:
# not overlap means |__interval_1___| |_interval_2__|
interval_1_end = interval_1[1]
interval_2_start = interval_2[0]
return interval_1_end <= interval_2_start
DP solution
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
if not intervals:
return 0
# initialize DP
dp = [0] * len(intervals)
dp[0] = 1
intervals.sort() # sort by starting point
for i in range(1, len(intervals)):
max_len = 1
interval = intervals[i]
for j in range(i):
if self._is_overlap(interval, intervals[j]):
# print('overlap', interval, intervals[j])
continue
else:
max_len = max(max_len, dp[j] + 1)
dp[i] = max_len
# print(dp)
return len(intervals) - max(dp)
def _is_overlap(self, i_1: List[int], i_2: List[int]) -> bool:
i_1_start = i_1[0]
i_2_end = i_2[1]
return not i_2_end <= i_1_start