• LeetCode220814-20_84、最长连续序列


    给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

    请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

    示例 1:

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

    来源:力扣(LeetCode)
    链接:https://leetcode.cn/problems/longest-consecutive-sequence
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    题解一、使用HashSet存储元素,去重,然后找连续数中最小的元素,若存在后续数值进行长度的累加。

    1. class Solution{
    2. public int longestConsecutive(int[] nums){
    3. Set<Integer> set = new HashSet<>();
    4. for(int num : nums){
    5. set.add(num);
    6. }
    7. int res = 0;
    8. //从HashSet用for循环遍历取值!!!去重!!!
    9. for(int num : set){
    10. if(!set.contains(num - 1)){
    11. int cur = num;
    12. int len = 1;
    13. while(set.contains(cur + 1)){
    14. cur++;
    15. len++;
    16. }
    17. res = Math.max(res, len);
    18. }
    19. }
    20. return res;
    21. }
    22. }

    题解二、使用HashSet,直接以自身为起始点,存在连续数值时不断对元素值进行累加,最终用插值表示最长连续距离。

    1. class Solution{
    2. public int longestConsecutive(int[] nums){
    3. Set<Integer> set = new HashSet<>();
    4. for(int num : nums){
    5. set.add(num);
    6. }
    7. int res = 0;
    8. for(int num : set){
    9. if(!set.contains(num - 1)){
    10. int cur = num;
    11. while(set.contains(cur + 1)){
    12. cur++;
    13. }
    14. res = Math.max(res, cur - num + 1);
    15. }
    16. }
    17. return res;
    18. }
    19. }

    题解三、使用HashMap存储数值对应的右边界,进行更新,和题解二一致,进行边界与起始值的差值求取最长距离。

    1. class Solution{
    2. public int longestConsecutive(int[] nums){
    3. Map map = new HashMap<>();
    4. for(int num : nums){
    5. map.put(num, num);
    6. }
    7. int res = 0;
    8. for(int num : nums){
    9. if(!map.containsKey(num - 1)){
    10. int right = map.get(num);
    11. while(map.containsKey(right + 1)){
    12. right++;
    13. }
    14. //更新右边界,防止连续序列的最左元素重复时再次进入while,进行遍历求right
    15. map.put(num, right);
    16. res = Math.max(res, right - num + 1);
    17. }
    18. }
    19. return res;
    20. }
    21. }

    题解四、动态规划,HashMap存储元素和他的最长连续距离,首次经过的元素才可进行求取,保证去重。只更新(num - left) 和(num + right)原因是,在中间的值已经在 (num - 1) 和 (num + 1)的key值条件下取过值了,不可能再用到。

    1. class Solution{
    2. public int longestConsecutive(int[] nums){
    3. Map map = new HashMap();
    4. int res = 0;
    5. for(int num : nums){
    6. if(!map.containsKey(num)){
    7. //每个元素最多最为一次左右元素被提及。
    8. //一次当作左边界被取到,下次在使用元素时,只能是作为右边界,因为上方的if条件
    9. int left = map.getOrDefault(num - 1, 0);
    10. int right = map.getOrDefault(num + 1, 0);
    11. int cur = left + right + 1;
    12. res = Math.max(res, cur);
    13. //将num添加入map,标记为已访问,和if条件呼应,若不标记,当左右left,right均可从map取到,不为0时,这个元素一直不被添加进map,会出现边界错误问题。
    14. map.put(num, 1);
    15. //更新左右边界,为下次用到左右边界数值时做准备。
    16. map.put(num - left, cur);
    17. map.put(num + right, cur);
    18. }
    19. }
    20. return res;
    21. }
    22. }

    题解五、并查集,size求取最长连续序列

    ①创建parent[]数组,作为相连根节点

    ②创建size[]数组,作为相连序列长度

    ③union合并时,相同根节点跳过(本题无相同根节点情况,因为都是只允许单次访问,并且进行根节点变换),不相同根节点,合并根节点的同时(新的指向已经存在的可降低树高),size求和

    ④find,压缩路径,递归找到根节点。

    ⑤求取最大size

    1. class Solution{
    2. public int longestConsecutive(int[] nums){
    3. Map map = new HashMap<>();
    4. UF uf = new UF(nums.length);
    5. for(int i = 0; i < nums.length; i++){
    6. if(map.containsKey(nums[i])) continue;
    7. if(map.containsKey(nums[i] - 1)){
    8. uf.union(i, map.get(nums[i] - 1));
    9. }
    10. if(map.containsKey(nums[i] + 1)){
    11. uf.union(i, map.get(nums[i] + 1));
    12. }
    13. map.put(nums[i], i);
    14. }
    15. return uf.getMaxSize();
    16. }
    17. }
    18. class UF{
    19. private int[] parent;
    20. private int[] size;
    21. public UF(int n){
    22. parent = new int[n];
    23. size = new int[n];
    24. Arrays.fill(size, 1);
    25. for(int i = 0; i < n; i++){
    26. parent[i] = i;
    27. }
    28. }
    29. public void union(int p, int q){
    30. int rootP = find(p);
    31. int rootQ = find(q);
    32. if(rootP == rootQ) return;
    33. parent[rootP] = rootQ;
    34. size[rootQ] += size[rootP];
    35. }
    36. public int find(int x){
    37. if(parent[x] != x){
    38. parent[x] = find(parent[x]);
    39. }
    40. return parent[x];
    41. }
    42. public int getMaxSize(){
    43. int res = 0;
    44. for(int i = 0; i < parent.length; i++){
    45. if(parent[i] == i){
    46. res = Math.max(res, size[i]);
    47. }
    48. }
    49. return res;
    50. }
    51. }

  • 相关阅读:
    基于JAVA临沂旅游咨询系统计算机毕业设计源码+数据库+lw文档+系统+部署
    Septentrio接收机二进制的BDS b2b改正数解码
    Kotlin协程:Flow的融合、Channel容量、溢出策略
    【vue3+ts后台管理】首页完成
    基于SSM校园一卡通管理系统
    Linux系统 (三)- 权限介绍
    贪心算法实例(一):多任务分配问题
    Win11提示无法安全下载软件怎么办?Win11无法安全下载软件
    SpringBoot与安全(Spring security)
    编辑器插件
  • 原文地址:https://blog.csdn.net/Zoro_666/article/details/126329010