LeetCode352 将数据流变为多个不相交区间

LeetCode352 将数据流变为多个不相交区间

1 题目

给你一个由非负整数 a1, a2, ..., an 组成的数据流输入,请你将到目前为止看到的数字总结为不相交的区间列表。

实现 SummaryRanges 类:

  • SummaryRanges() 使用一个空数据流初始化对象。
  • void addNum(int val) 向数据流中加入整数 val 。
  • int[][] getIntervals() 以不相交区间 [starti, endi] 的列表形式返回对数据流中整数的总结

2 思路

对于一组数据,

1 2 3 5 7 8

将连续的数字归纳到一个区间内,因此该数组的表示为[[1,3][5,5][7,8]]

方法1:列表+二分查找

使用一个数组存储维护所有的不相交区间,当有新元素添加时,通过二分查找的方式找到添加的位置,

  • 如果在区间内,例如[1,3]中添加2,此时2元素已经存在。则直接跳过,
  • 如果不在区间内,当添加的元素在区间的左右边界时,则需要考虑是否存在合并区间的情况。
    • 当元素正好是上一个区间的右边界+1,且是下一个区间的的左边界-1,此时需要合并区间,例如[0,0][2,3],添加1,此时合并区间为[0,3]
    • 当元素正好是上一个区间的右边界+1,或者是下一个区间的的左边界-1,更新区间的左右边界即可
    • 当元素不满足以上情况,则单独成为一个区间[1,1][5,5]添加3后为[1,1][3,3][5,5]

方法2:并查集

使用一个10000长度的数组parent模拟该区间,数组内存储该元素父元素的之,初始化时,每个元素单独成区间。

使用一个set集合存储出现过的元素

为集合建立并查集,集合的父亲代表连通集的右边界

每次获取区间进行一次并查集的查询操作,相邻的区间会被合并,遍历每个出现过的元素(从小到大排序),

  • 如果元素小于结果集的尾值,则意味着该元素已经包含在结果集中,直接跳过,
  • 如果小于尾值,则需要以该元素为左边界建立区间,然后根据parent数组查询右边界即可

3 Code

import bisect
class SummaryRanges:
    def __init__(self):
        #模拟区间
        self.p=[i for i in range(100005)]
        #存储出现过的元素
        self.nums=[]
        
    def addNum(self, val: int) -> None:
        if val not in self.nums:
            #保证插入后数组是有序的
            bisect.insort(self.nums,val)
        #该元素的右边界是它下一个元素的右边界
        self.p[val]=self.p[val+1]

    def parent(self,num):
        #单独成区间,直接返回该元素
        if num==self.p[num]:
            return num
        #递归查找父元素
        self.p[num]=self.parent(self.p[num])
        return self.p[num]       

    def getIntervals(self) -> List[List[int]]:
        res=[]
        #遍历每个元素
        for i in range(len(self.nums)):
            #大于结果集尾值则跳过
            if len(res)!=0 and res[-1][1]>=self.nums[i]:
                continue
            #将左右边界插入
            res.append([self.nums[i],self.parent(self.nums[i])-1])
        return res
posted @ 2021-10-09 18:03  流光之中  阅读(81)  评论(0)    收藏  举报