leetcode 2276. Count Integers in Intervals(python)

823 阅读2分钟

描述

Given an empty set of intervals, implement a data structure that can:

  • Add an interval to the set of intervals.
  • Count the number of integers that are present in at least one interval.

Implement the CountIntervals class:

  • CountIntervals() Initializes the object with an empty set of intervals.
  • void add(int left, int right) Adds the interval [left, right] to the set of intervals.
  • int count() Returns the number of integers that are present in at least one interval.

Note that an interval [left, right] denotes all the integers x where left <= x <= right.

Example 1:

Input
["CountIntervals", "add", "add", "count", "add", "count"]
[[], [2, 3], [7, 10], [], [5, 8], []]
Output
[null, null, null, 6, null, 8]

Explanation
CountIntervals countIntervals = new CountIntervals(); // initialize the object with an empty set of intervals. 
countIntervals.add(2, 3);  // add [2, 3] to the set of intervals.
countIntervals.add(7, 10); // add [7, 10] to the set of intervals.
countIntervals.count();    // return 6
                           // the integers 2 and 3 are present in the interval [2, 3].
                           // the integers 7, 8, 9, and 10 are present in the interval [7, 10].
countIntervals.add(5, 8);  // add [5, 8] to the set of intervals.
countIntervals.count();    // return 8
                           // the integers 2 and 3 are present in the interval [2, 3].
                           // the integers 5 and 6 are present in the interval [5, 8].
                           // the integers 7 and 8 are present in the intervals [5, 8] and [7, 10].
                           // the integers 9 and 10 are present in the interval [7, 10].

Note:

1 <= left <= right <= 10^9
At most 10^5 calls in total will be made to add and count.
At least one call will be made to count.

解析

根据题意,给定一组空的区间集合,实现一个数据结构,它可以:

  • 将间隔添加到间隔集。
  • 计算至少一个区间中存在的整数个数。

实现 CountIntervals 类:

  • CountIntervals() 用一组空的间隔来初始化对象
  • void add(int left, int right) 将区间 [left, right] 添加到区间集合中,这是闭区间
  • int count() 返回出现在至少一个区间内的整数个数

比赛的时候我知道这道题要用到二分法,但是最后写的代码又臭又长,后来看了大佬的解释才知道,原来这是在考察珂朵莉树算法,大家可以去看一下大佬的解释,我这里就不多介绍了。

整体的思路就是在执行 add 的时候,将新来的 [left,right] 区间尽量融入到与其有覆盖交集的更大的区间中,这样就可以将区间集合不断缩小,当然如果没有覆盖的区间,那么我们就在区间集合中新增加一个区间。

时间复杂度为 O(NlogM) 因为一共调用 N 次,每次时间复杂度为 O(logM) ,M 为区间集合数量。空间复杂度为 O(M),可能会有 M 个区间段 ,N 是调用方法的次数。

解答

from sortedcontainers import SortedDict
class CountIntervals(object):
    def __init__(self):
        self.result = 0
        self.d = SortedDict()

    def add(self, left, right):
        """
        :type left: int
        :type right: int
        :rtype: None
        """
        idx = self.d.bisect_left(left)
        while idx<len(self.d) and self.d.values()[idx] <= right:
            r, l = self.d.popitem(idx)
            left = min(l, left)
            right = max(r, right)
            self.result -= r-l+1
        self.result += right - left + 1
        self.d[right] = left
        
    def count(self):
        """
        :rtype: int
        """
        return self.result			

运行结果

73 / 73 test cases passed.
Status: Accepted
Runtime: 1366 ms
Memory Usage: 54 MB

原题链接

leetcode.com/contest/wee…

您的支持是我最大的动力