首页 > 其他分享 >leet code 128. 最长连续序列

leet code 128. 最长连续序列

时间:2023-10-10 13:31:44浏览次数:35  
标签:map leet code sz nums int num 128 public

128. 最长连续序列

题目描述

给定一个未排序的整数数组 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

提示:

leet code 128. 最长连续序列_数组

leet code 128. 最长连续序列_数组_02

题目解析

题目要求 O(n) 的时间复杂度解决此问题,但是没有头绪。先忽略这个限制

  • 笨方法对数组进行排序
  • 然后再进行遍历

时间复杂度 O(logN)

public int longestConsecutive(int[] nums) {
        Arrays.sort(nums);
        int ans = 0,idx = 0,n = nums.length;
        while(idx < n) {
            // 定义下一个下标位置
            int step = idx + 1;
            // 记录长度,初始化1 是因为最小为 1
            int cnt = 1;
            while(step < n) {
                // 连续的情况.
                if(nums[step] == nums[step - 1] + 1) {
                    cnt++;
                    step++;
                } else if(nums[step] == nums[step - 1]) {
                    // 相等的情况.
                    step++;
                } else if(nums[step] > nums[step - 1] + 1) {
                    // 跳出循环的情况.
                    break;
                }
            }
            ans = Math.max(ans, cnt);
            idx = step;
        }
        return ans;
    }
  • 经过复杂的解法,发现有了一点思路
  • 可以使用map集合来保存当前元素对应的 连续子序列 的长度
  • 然后不断更新
  • 遍历到一个元素,只需要判断 其本身、其本身减一和其本身加一 是否存在于 哈希表中即可
  • 然后分别进行对应的逻辑计算.

code 尝试 O(N)

class Solution {
    public int longestConsecutive(int[] nums) {
        Map<Integer, Integer> map = new HashMap<>();
        int ans = 0;
        for (int num : nums) {
            if (map.containsKey(num)) {
                continue;
            } else {
                int before = num - 1;
                int next = num + 1;
                if (map.containsKey(before) || map.containsKey(next)) {
                    int beforeLen = map.getOrDefault(before, 0);
                    int nextLen = map.getOrDefault(next, 0);
                    int len = beforeLen + nextLen + 1;
                    map.put(num, len);
                    //  这里的  while 更新会导致超时
                    while (map.containsKey(before) && map.get(before) != len) {
                        map.put(before, len);
                        before--;
                    }
                    while (map.containsKey(next) && map.get(next) != len) {
                        map.put(next, len);
                        next++;
                    }
                } else {
                    map.put(num, 1);
                }
                ans = Math.max(ans, map.get(num));
            }
        }
        return ans;
    }
}
  • 测试发现会超时

O(N) 解法

  • 通过哈希表的方式,发现 数组内连续的子序列可以归属到一个集合中去
  • 刚刚好适合用并查集来解决问题
  • 以数组 nums = [100, 4, 200, 1, 3, 2]为例
  • 只需要遍历一次数组+利用哈希表
  • 遍历到当前元素的时候
  • 首先判断是否在哈希表中存在,如果存在不重复处理
  • 然后 判断其 加一 和 减一 的值是否在哈希表中存在
  • 如果存在则 进行并查集合并操作
  • 如上图,遍历到 元素3 哈希表中存在 4,则 元素 3和4所对应的集合进行合并
  • 遍历到元素2 元素1和3在哈希表中存在,则 合并其所在的集合
  • 利用并查集的特性,求出元素最多的集合直接返回

show code

class Solution {
    public int longestConsecutive(int[] nums) {
        if(nums.length == 0) {
            return 0;
        }
        // 首先定义一个哈希表
        Map<Integer, Integer> map = new HashMap<>();
        // 初始化并查集.
        Union union = new Union(nums.length);

        // 开始遍历nums
        for (int i = 0; i < nums.length; i++) {
            int num = nums[i];
            if (map.containsKey(num)) {
                continue;
            }
            int less = num - 1;
            int up = num + 1;
            if (map.containsKey(less) || map.containsKey(up)) {
                // 表示当前元素可以构成一个长度大于1 的子序列.
                if (map.containsKey(less)) {
                    union.union(map.get(less), i);
                }
                if (map.containsKey(up)) {
                    union.union(map.get(up), i);
                }
            }
            map.put(num, i);
        }

        return union.max;
    }
}

class Union {

    public int count;
    public int[] arr;
    // sz[i] 表示以 i 为根集合中的元素个数
    public int[] sz;

    public int max;

    public Union(int count) {
        this.count = count;
        arr = new int[count];
        sz = new int[count];
        for (int i = 0; i < count; i++) {
            arr[i] = i;
            // 初始化1个.
            sz[i] = 1;
        }
        max = 1;
    }

    public int find(int val) {
        // 不断查询自己的父节点,直到到达根节点
        while (val != arr[val]) {
            val = arr[val];
        }
        return val;
    }

    public boolean isConnected(int a, int b) {
        return find(a) == find(b);
    }

    public void union(int a, int b) {
        // rootA、rootB 分别表示  a b 所属的集合编号.
        int rootA = find(a);
        int rootB = find(b);

        if (rootA == rootB) {
            // 表示同一个集合
            return;
        }
        max = Math.max(max, sz[rootA] + sz[rootB]);
        if (sz[rootA] < sz[rootB]) {
            // 元素个数少的集合  合并到 元素个数多的集合
            // 这里 a 向 b 合并
            arr[rootA] = rootB;
            // b 集合的元素个数增加
            sz[rootB] += sz[rootA];
        } else {
            arr[rootB] = rootA;
            sz[rootA] += sz[rootB];
        }
    }

}

标签:map,leet,code,sz,nums,int,num,128,public
From: https://blog.51cto.com/u_16079703/7791243

相关文章

  • Educational Codeforces Round 156 (Rated for Div. 2)
    EducationalCodeforcesRound156(RatedforDiv.2)A.SumofThree解题思路:如果\(n\leq6或n=9\),无解。若\(n\%3==0,t=\lfloor\frac{3}{n}\rfloor\):若\(t=0\)构造\(1,4,n-5\)否则,构造\(t-3,t,t+3\)若\(n\%3==1:构造1,2,n-3\)若\(n......
  • Codeforces Round 902 (Div. 2, based on COMPFEST 15 - Final Round)
    目录写在前面ABCDE写在最后写在前面比赛地址:https://codeforces.com/contest/1877。呜呜铃果唱歌太好听了、、、我宣布是第二喜欢的声线,第三喜欢是东北切蒲英,第一喜欢绝赞招募中。这下不得不成为数码推了、、、A答案为\(-\suma_i\)。懒得写代数式子推了,赛时看完题直接......
  • vscode常用快捷键
    快捷键打开/关闭左侧工作区ctrl+B格式化ctrl+Kalt+shift+f更改颜色主题Ctrl+K+T清空控制台cls关闭当前标签Ctrl+F4或Ctrl+W新打开一个编辑器ctrl+shift+n折叠所有代码ctrl+shift+[-]ctrl+k,ctrl+0展开所有代码ctrl+shift+[+]将文件夹保存为项目打开文件......
  • Educational Codeforces Round 152 (Div. 2) D. Array Painting(双指针)
    EducationalCodeforcesRound152(Div.2)D.ArrayPainting//思路:双指针找连续正数段//若段中出现2,则更新两头的0的情况,若为涂色则改为true//若无2,则优先更新左侧0,若左0已经为true,则更新右侧0//数组开头结尾特判#defineintlonglong#defineldlongdoubleusingnam......
  • oracle中to_char(), to_date() ,ROUND(),NVL(), DECODE(), EXTRACT()等函数的使用
    1.to_char()将时间日期按照指定的格式输出,得到的是字符串,而非date类型。只要被转换的是一个日期,yyyy,mm,dd中间加不加连接符,加什么连接符都可以2.todate()将字符串按照指定的格式输出,得到的是日期类型。第一个参数的yyyy,mm,dd之间有没有连接符。如果有,那么第二个参数必须有......
  • 练习记录-cf-Educational Codeforces Round 156 (Rated for Div. 2)(A-C)
    好久没打了还是就出了三道不过还好没掉分A.SumofThree就是问能不能把一个数拆成三个不同的且都不能被三整除的数我的思路就是拆成1+2+一个大于等于4的数如果拆了后另一个数是%3==0那么我拆成1+4它肯定就不被整除然后判下相同#include<bits/stdc++.h>#defineclose......
  • Codeforces Round 902 (Div. 2) C. Joyboard 规律
    CodeforcesRound902(Div.2)C.Joyboard//思路:在k=1,k=2,k=3时有解//当k=1时为全0//当k=2时,若m>=n,则先是0然后为1~n,最后一位可以为n的倍数也符合,即n+m/n-1//若m<n则为1~m即m//当k=3时,只能在n+1位是第3个不同情况(大于n),且不能为n的倍数,即(m-n)-(m/n-1)//只......
  • Implicit Autoencoder for Point-Cloud Self-Supervised Representation Learning论文
    ImplicitAutoencoderforPoint-CloudSelf-SupervisedRepresentationLearning2023ICCV*SimingYan,ZhenpeiYang,HaoxiangLi,ChenSong,LiGuan,HaoKang,GangHua,QixingHuang*;ProceedingsoftheIEEE/CVFInternationalConferenceonComputerVision......
  • AES key — encoded in the machine readable zone of a European ePassport
    AESkey—encodedinthemachinereadablezoneofaEuropeanePassport题目地址AESkey—encodedinthemachinereadablezoneofaEuropeanePassport解题过程第一步:补全给出的密钥通过查阅题目附录里提到的文档,可以找到校验位的具体机制,依据解释可求出初始密钥"?......
  • Win10安装VSCode并配置Python环境(完美避开踩过的所有坑)
    安装VScode下载vscode下载链接:https://code.visualstudio.com/Download根据自己的电脑型号下载对应的版本。我下载的是windows/UserInstaller,但是使用时会提示“”。所以,推荐下载SystemInstaller版本。两者区别可以自行百度,或......