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

Posted Yawn__

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode——将数据流变为多个不相交区间相关的知识,希望对你有一定的参考价值。

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

(1)模拟

假设当前第一次加入一个值为 val 的元素,那么只有四种情况:

  • (1)数据流中已经被加入了 val - 1 和 val + 1 两个元素,但因为 val 第一次被加入,所以当前数据流的区间列表中,一定存在两个区间,一个以 val - 1 结尾,另一个以 val + 1 开头。那么,加入 val 后,这两个区间就可以被合并为一个区间。
  • (2)数据流中已经被加入了 val - 1,但没有 val + 1。此时,区间列表中一定存在一个区间,以 val - 1 结尾,我们将 val 加入后,只需将该区间的右端点修改为 val 即可。
  • (3)数据流中已经被加入了 val + 1,但没有 val - 1。与第二种情况类似,我们将以 val + 1 为左端点的区间左端点改为 val 即可。
  • (4)数据流中 val - 1 和 val + 1 均未出现过,此时 val 将自己形成一个独立的区间。

为了快速找到以某个值为左端点或右端点的区间,我们可以每次加入一个整数后,都将区间列表排序,以保证可以使用二分法。

注意:

由于前三种情况都需要找到以某个值为左端点或者右端点的区间在区间列表中的位置,

所以我们在代码中封装了一个二分法函数:binarySearch,用于指明要找的是左端点还是右端点 (0左1右)

看看代码:

class SummaryRanges 
    List<int[]> tempList;
    Set<Integer> numSet;
    public SummaryRanges() 
        tempList = new ArrayList<>();
        numSet = new HashSet<>();
    

    public void addNum(int val) 
        if (numSet.contains(val)) 
                return;
        
        numSet.add(val);
        //需要合并 [..., val - 1] 和 [val + 1, ...] 两个区间
        if (numSet.contains(val-1) && numSet.contains(val+1)) 
            int left = binarySearch(val-1,1);
            int right = binarySearch(val+1,0);
            tempList.get(left)[1] = tempList.get(right)[1];
            tempList.remove(right);
         else if (numSet.contains(val+1)) 
        //val + 1 出现过,说明有以 val + 1 为左端点的区间
            int ans = binarySearch(val+1,0);
            tempList.get(ans)[0] = val;
         else if (numSet.contains(val-1)) 
        //有以 val - 1 为右端点的区间
            int ans = binarySearch(val-1,1);
            tempList.get(ans)[1] = val;
         else 
            // 左右都未出现,val 形成一个独立区间
            tempList.add(new int[]val,val);
        
        Collections.sort(tempList,(o1, o2) -> o1[0]-o2[0]);
    

    public int[][] getIntervals() 
        int lenN = tempList.size();
        int[][] ans = new int[lenN][2];
        for(int i = 0; i < lenN; i++) 
            ans[i] = tempList.get(i);
        
        return ans;
    
    
    //pos 指明要找的是左端点还是右端点 0左1右
    public int binarySearch(int target ,int pos)
        int left = 0, right = tempList.size()-1;
        while (left <= right) 
            int mid = left + (right - left) / 2;
            int tempVal = tempList.get(mid)[pos];
            if (tempVal == target) 
                return mid;
             else if (tempVal < target) 
                left = mid + 1;
             else 
                right = mid - 1;
            
        
        return -1;
    

/**
 * Your SummaryRanges object will be instantiated and called as such:
 * SummaryRanges obj = new SummaryRanges();
 * obj.addNum(val);
 * int[][] param_2 = obj.getIntervals();
 */

以上是关于Leetcode——将数据流变为多个不相交区间的主要内容,如果未能解决你的问题,请参考以下文章

《LeetCode之每日一题》:173.将数据流变为多个不相交区间

LeetCode 187. 重复的DNA序列 / 352. 将数据流变为多个不相交区间 / 441. 排列硬币

数据结构与算法之深入解析“将数据流变为多个不相交区间”的求解思路与算法示例

leetcode 435. 无重叠区间贪心策略:优先保留结尾小且不相交的区间,即局部最优连续区间

leetcode 435.无重叠区间贪心策略:优先保留结尾小且不相交的区间,即局部最优连续区间

leetcode 435.无重叠区间贪心策略:优先保留结尾小且不相交的区间,即局部最优连续区间