Skip to content
本页目录

0128-最长连续序列

https://leetcode.cn/problems/longest-consecutive-sequence

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

示例 1:

输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

示例 2:

输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9

提示:

0 <= nums.length <= 10^5
-10^9 <= nums[i] <= 10^9

思路 【官方】

  1. 暴力思路,选定一个数,nums[i] 依次递增,看数组中是否存在nums[i]+,是的话就加+1,直到停止。 这个方法会循环两层,复杂度 O(n^2)
  2. 将所有数字去重加入Hash表,从 nums[i] 递增,如果发现 Hash 表中存在 key 则继续,直到停止。
  3. 将第二步优化,比如 数组中有 3 和 2 ,那么从3开始计数得出的结果,一定比从2计数得出的结果+1,所以没有必要计算3,直接找没有前驱的节点开始计算 因为省略了所有带有前驱节点的计算,所以总体复杂度是 O(n)

参考代码

csharp
public class Solution {
    public int LongestConsecutive(int[] nums) {
    	HashSet<int> set = new HashSet<int>();
    	for(int i=0; i<nums.Length; i++){
    		if(!set.Contains(nums[i])){
    			set.Add(nums[i]);
    		}
    	}
    	int maxStrike = 0;
    	int curStrike = 0;
    	foreach(int key in set){
    		int preKey = key - 1;
    		if(!set.Contains(preKey)){
    			curStrike = 1;
    			int nextKey = key+1;
    			while(set.Contains(nextKey)){
    				curStrike++;
    				nextKey++;
    			}
    			maxStrike = Math.Max(maxStrike,curStrike);
    		}
    	}
    	return maxStrike;
    }
}

复习:20220520

题目要求 O(n) 时间复杂度, 所以我们需要借助空间。 使用哈希表记录每个数字是否出现过。 考虑记录最小数字 min 和 最大数字 max ,然后根据哈希表的key统计连击,后来发现这样效率很低,会超时。 比如 [1,2,99999999] 这样的数组. 考虑根据哈希表的key,然后检查 key+1 是否存在,是则连击,否则 strike = 0; 再考虑到,比如已经有连续的数 2,3,4 存在,所以从4和3统计就没有意义,因为统计2的时候+1,肯定会统计到3和4,所以我们要找到没有前驱节点的开始统计才有意义,即 prekey = key-1不存在的.

csharp
public class Solution {
    public int LongestConsecutive(int[] nums) {
        Dictionary<int,int> dict = new Dictionary<int,int>();
        for(int i=0; i<nums.Length; i++){
            if(!dict.ContainsKey(nums[i])){
                dict.Add(nums[i],1);
            }
        }
        int maxStrike = 0;
        //循环key开始统计
        foreach(int key in dict.Keys){
            int preKey = key - 1;
            if(!dict.ContainsKey(preKey)){
                int count = 0;
                int strike = 1;
                int nextKey = key + 1;
                while(dict.ContainsKey(nextKey)){
                    strike++;
                    nextKey++;
                }
                maxStrike = Math.Max(maxStrike,strike);
            }
        }
        return maxStrike;
    }
}

并查集:20220703

csharp
public class Solution {

    public class UF{
        private int[] parent;
        private int[] size;

        public UF(int n){
            parent = new int[n];
            size = new int[n];
            for(int i=0; i<n; i++){
                parent[i] = i;
                size[i] = 1;
            }
        }

        public void union(int p, int q){
            int rootP = find(p); 
            int rootQ = find(q);
            if(rootP == rootQ){
                return;
            }
            parent[rootP] = rootQ;
            size[rootQ] += size[rootP]; 
        }

        public int find(int x){
            //路径压缩
            if(parent[x] != x){
                parent[x] = find(parent[x]);
            }
            return parent[x];
        }

        public int getMaxConnectSize(){
            int maxSize = 0;
            for(int i=0; i<parent.Length; i++){
                if(i == parent[i]){
                    maxSize = Math.Max(maxSize, size[i]);
                }
            }
            return maxSize;
        }

    }

    public int LongestConsecutive(int[] nums) {
        int n = nums.Length;
        UF uf = new UF(n);
        Dictionary<int,int> dict = new Dictionary<int,int>();
        for(int i=0; i<n; i++){
            if(dict.ContainsKey(nums[i])){
                continue;
            }

            if(dict.ContainsKey(nums[i] - 1)){ //查看是否前一个存在,是的话就连接
                uf.union(i, dict[nums[i]-1]);
            }
            if(dict.ContainsKey(nums[i] + 1)){ //查看是否后一个存在,是的话就连接
                uf.union(i, dict[nums[i]+1]);
            }
            dict.Add(nums[i],i);
        }
        return uf.getMaxConnectSize();
    }
}

Released under the MIT License.