Loading

数组中的最长连续序列

数组中的最长连续序列

题目:数组中的最长连续子序列

《程序员代码面试指南》第75题 P248 难度:尉★★☆☆

这题我一上来想到先排序再找最长序列,不过就算使用最快的排序算法,时间复杂度也达到了O(NlogN),不符合题目要求的O(N)

介绍两种解法:

首先是书中使用哈希表的解法:

  1. 生成哈希表mapkey代表遍历过的某个数value代表key这个数所在的最长连续序列的长度。同时map还可以表示arr中的一个数之前是否出现过
  2. 从左到右遍历arr。如果arr[i]之前出现过直接遍历下一个数。如果arr[i]没出现过,首先在map中加入记录(arr[i],1),代表目前arr[i]单独作为一个连续序列。然后看map中是否含有arr[i]-1,如果利用map得到该序列的长度,记为lenA最小值leftA最大值rightA只在map中更新与leftA和rightA有关的记录更新成(leftA,lenA)和(rightA,lenA)。对于arr[i]+1亦然,更新成(leftB,lenB)(rightB,lenB)
  3. 遍历过程中用全局变量max记录每次合并出的序列的长度最大值,最后返回max。

整个过程中,只是每个连续序列最小值和最大值在map中的记录有意义,中间数的记录不会再更新,因为再也不会用到。如果一个没出现的数能够把某个连续区间扩大,或把某两个连续区间连在一起只需要map中有关这个连续区间最小值和最大值的记录

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

public int merge(HashMap<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;
}

力扣解法:

首先将原数组放入HashSet去重,然后对于每个数x,如果在set中存在前驱数x-1,则直接跳过。如果不存在,则不断尝试匹配x+1,x+2,……是否存在,得到最长序列xx+1x+2……x+y长度为y+1不断枚举更新答案即可,最后取最长连续序列的长度返回

class Solution {
    public int longestConsecutive(int[] nums) {
        Set<Integer> num_set = new HashSet<Integer>();
        for (int num : nums) {
            num_set.add(num);
        }

        int longestStreak = 0;

        for (int num : num_set) {
            if (!num_set.contains(num - 1)) {
                int currentNum = num;
                int currentStreak = 1;

                while (num_set.contains(currentNum + 1)) {
                    currentNum += 1;
                    currentStreak += 1;
                }

                longestStreak = Math.max(longestStreak, currentStreak);
            }
        }

        return longestStreak;
    }
}

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/longest-consecutive-sequence/solution/zui-chang-lian-xu-xu-lie-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
posted @ 2022-03-28 20:05  幻梦翱翔  阅读(111)  评论(0)    收藏  举报