zoukankan      html  css  js  c++  java
  • "Coding Interview Guide" -- 数组中的最长连续序列

    题目

      给定无序数组arr,返回其中最长的连续序列的长度

      举例,arr=[100,4,200,1,3,2],最长的连续序列为[1,2,3,4],所以返回4

    分析

      HashMap是一种存储键值对(key-value)的数据结构,基于哈希表实现Map接口。可以使用这种数据结构来寻找最长连续序列的长度

      首先生成一个HashMap的实例map,其中key表示数组元素,value表示该元素所在连续序列的长度。从头开始遍历数组,如果元素arr[i]不在map中,则将(arr[i], 1)放入map中,代表目前arr[i]单独作为一个连续序列,然后查看map中是否有arr[i]-1,如果有,则说明arr[i]-1所在的连续序列可以和arr[i]合并,合并后记为A序列,利用map可以得到A序列的长度,记为lenA,序列的左边界元素记为leftA,右边界元素记为rightA,只在map中更新合并后的序列的相关信息,即两个边界信息和长度信息,更新成(leftA, lenA)和(rightA, lenA);再查看map中是否有arr[i]+1,如果有,说明arr[i]+1所在的连续序列可以和序列A合并,合并后记为B序列。通过map可以得到B序列的长度,记为lenB,序列B的左边界元素记为leftB,右边界元素记为rightB,只在map中更新合并后序列的相关信息,即两个序列边界信息和长度信息,更新成(leftB, lenB)和(rightB, lenB)。遍历过程中用一个全局变量max记录每次合并后,所有连续序列中长度的最大值,即为最长连续序列的长度。

      遍历过程中只需要更新合并后序列的两个边界信息和序列长度信息,因为我们判断两个序列是否可以合并,是根据这两个序列的边界信息判断的,和这两个序列的中间元素无关,所以对于这两个序列的中间元素,不用更新其value值。

     1 public int longestConsecutive(int[] arr)
     2 {
     3     if(arr == null || arr.length == 0)
     4     {
     5       return 0;
     6     }
     7 
     8     HashMap<Integer, Integer> map = new HashMap<>();
     9     int max = 1;
    10 
    11     for(int i = 0; i < arr.length; i++)
    12     {
    13         if(!map.containsKey(arr[i]))
    14       {
    15             map.put(arr[i], 1);
    16             if(map.containsKey(arr[i]-1))         // 如果map中存在arr[i]-1,说明arr[i]可以和arr[i]-1所在的序列合并
    17           {
    18             max = Math.max(max, merge(map, arr[i]-1, arr[i])); 
    19           }
    20           if(map.containsKey(arr[i]+1))         // 如果map中存在arr[i]+1,说明arr[i]所在的序列可以和arr[i]+1所在的序列合并
    21           {
    22             max = Math.max(max, merge(map, arr[i], arr[i]+1));
    23           }
    24       }
    25     }
    26     return max;
    27 }
    28 
    29 public int merge(HashMap<Integer, Integer> map, int less, int more)
    30 {
    31     int left = less - map.get(less) + 1;     // 合并后连续序列的左边界
    32     int right = more + map.get(more) - 1;    // 合并后连续序列的右边界
    33     int len = right - left + 1;              // 合并后连续序列的长度
    34     map.put(left, len);                      // 更新合并后连续序列的左边界元素的value,即左边界元素所在连续序列的长度
    35     map.put(right, len);                     // 更新合并后连续序列的右边界元素的value,即右边界元素所在连续序列的长度
    36     return len;
    37 }
    38      

    来源:左程云老师《程序员代码面试指南》

  • 相关阅读:
    利用CWinThread实现跨线程父子MFC窗口
    GetForgroundWindow函数的不确定性——BUG笔记
    DLL动态链接库的创建
    php正则讲解 及与 js的正则比较
    cookie和session的讲解
    两种排序的方法 冒泡法 插入法 封装版
    php中获取当前时间
    文件下载及header方法介绍
    文件上传
    二分法封装版
  • 原文地址:https://www.cnblogs.com/OoycyoO/p/10881444.html
Copyright © 2011-2022 走看看