LeetCode-128 找出数字连续的最长序列 原创O(n)解法

题目详情

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
你可以设计并实现时间复杂度为 O(n) 的解决方案吗?

题目分析

该题难点在于O(n),所以不能用排序

这里很明显,暴力解法是O(n2),那么就需要空间换时间。
于是我便想到利用map。
其中是<Integer,Integer>,然后代表的是区间.
例如,区间[3,5],hashmap中如此存放:(3:5),(5,3),左边界对应右边界,右边界对应左边界。
然后每加入一个新的元素,判断其-1,+1是否在hashmap中,则有四种可能,具体的时间复杂度是O(n),满足要求,但是常数时间有点大,所以速度不是很快.
在代码中我贴了详细的注释,代码有点长,但很多是重复操作,可以大大简化。不难理解。

代码

class Solution {
    
    
    //要求O(n)
    //思路有了,就是之前那个,可能不太正规
    //就是Map中维护连续的边界
    //左:右;右:左
    //每次加入一个新的元素,则判断其-1,+1在不在map中
    //四种情况,如果都在,则将左区间的左边界的值设为右区间的右边界的值,然后同理
    //如果只有一个在,则举例,左的右边界+1,当前值的左边界为原始左边界,删除之前的右边界
    //如果没有,则直接创建新的
    //这样就是O(n)的,而且空间复杂度其实不高
    //你加入进去是2:2,然后有个3,你将2:2设置为2:3,3,设置成2。如果是1,那么就是1:2,就是左右的设置不同

    public int longestConsecutive(int[] nums) {
    
    
        //区间集合
        //左里放右,右里放左
        Map<Integer,Integer> intervals = new HashMap<>();
        Set<Integer> set = new HashSet<>();
        int max = 0;
        //遍历序列
        for(int num : nums){
    
    
            if(set.contains(num))continue;
            set.add(num);
            if(intervals.containsKey(num-1)&&intervals.containsKey(num+1)){
    
    
                //将区间合并,只留下边界信息,中间删除
                int leftIntervalLeftBorder = intervals.get(num-1);
                int rightIntervalRightBorder =  intervals.get(num+1);
                intervals.remove(num-1);
                intervals.remove(num+1);
                intervals.put(leftIntervalLeftBorder,rightIntervalRightBorder);
                intervals.put(rightIntervalRightBorder,leftIntervalLeftBorder);
                max = Math.max(rightIntervalRightBorder-leftIntervalLeftBorder+1,max);
            }
            else if(intervals.containsKey(num-1)){
    
    
                int leftIntervalLeftBorder = intervals.get(num-1);
                intervals.remove(num-1);
                intervals.put(leftIntervalLeftBorder,num);
                intervals.put(num,leftIntervalLeftBorder);
                max = Math.max(num-leftIntervalLeftBorder+1,max);
            }
            else if(intervals.containsKey(num+1)){
    
    
                int rightIntervalRightBorder = intervals.get(num+1);
                intervals.remove(num+1);
                intervals.put(rightIntervalRightBorder,num);
                intervals.put(num,rightIntervalRightBorder);
                max = Math.max(rightIntervalRightBorder-num+1,max);
            }
            else{
    
    
                intervals.put(num,num);
                max = Math.max(1,max);
            }
        }
        return max;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_34687559/article/details/110433875