最长连续序列

给定一个未排序的整数数组,找出最长连续序列的长度。

说明

要求你的算法复杂度为O(n)

样例

给出数组[100, 4, 200, 1, 3, 2],这个最长的连续序列是 [1, 2, 3, 4],返回所求长度 4

 

由于复杂度为o(N), 我们用hashmap来记录每个数所在的最长子序列长度。

刚开始遍历数组时,比如遍历到3这个数,若3已经在map中了,跳过,表明已经处理过了;若3不在map中,先加入到map里,value为1,表示3目前所在的最长连续序列长度为1;

接着就要考虑3的前后两个数是否在map中,若存在,则3的value需要更新;

用一个merge()方法去计算合并完之后的序列长度。

比如,对3来说,2存在于map中,他的序列长度为a。那么可以求得,2所在序列的起始长度为2-a+1. 注意,只有序列的首末元素才能如此计算,也就是我们要确保计算的元素一定是首末元素。再令4所在序列的长度为b,则该序列末尾元素为4+b-1. 

至此,我们求得了一个连续序列:[2-a+1, 4+b-1]

对于这样一个序列,只有他的首末元素暴露在计算中,故只更新首末元素在map中的value值即可。

因为对于任意一个元素,我们只看他能否连接两个子序列,或者他能否跟在某序列屁股后面形成新序列。

public int longestConsecutive(int[] num) {
        if(num == null || num.length == 0) return 0;
        int max = 1;
        Map<Integer, Integer> map = new HashMap<>();
        for(int i = 0; i < num.length; i++){
            if(!map.containsKey(num[i])){
                map.put(num[i], 1);
                if(map.containsKey(num[i] - 1)){
                    max = Math.max(max, merge(map, num[i]- 1, num[i]));
                }
                if(map.containsKey(num[i] + 1)){
                    max = Math.max(max, merge(map, num[i], num[i] + 1));
                }
            }
        }

        return max;

    }

    public int merge(Map<Integer, Integer> map, int less, int more){
        int left = less - map.get(less) + 1;
        int right = more + map.get(more) - 1;
        int len = right - left + 1;
        map.put(left, len);
        map.put(right, len);

        return len;
    }

 

posted @ 2017-09-21 15:54  贾斯彼迭  阅读(874)  评论(0编辑  收藏  举报