zoukankan      html  css  js  c++  java
  • 递归和动态规划问题:数组中的最长连续序列

    题目

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

    举例

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

    难度

      二星

    解答

      本题利用哈希表可以实现时间复杂度为 O(N), 额外空间复杂度为 O(N) 的方法。具体实现方法如下:

      1. 生成哈希表 HashMap<Integer, Integer> map,key 代表遍历过的某个数,value 代表 key 这个数所在的最长连续序列的长度。同时 map 还可以表示 arr 中的一个数之前是否出现过。

      2. 从左到右遍历 arr, 假设遍历到 arr[i]。如果 arr[i] 之前出现过,直接遍历下一个数,只处理之前没出现过的 arr[i]。首先在 map 中加入记录(arr[i], 1), 代表目前 arr[i] 单独作为一个连续序列。然后看 map 中是否含有 arr[i] - 1,如果有,则说明 arr[i] - 1 所在的连续序列可以和 arr[i] 合并,合并后记为 A序列。利用 map 可以得到 A 序列的长度,记为 lenA,最小值记为 leftA,最大值记为 rightA,只在 map 中更新与 leftA 和 rightA 有关的记录,更新成 (leftA, lenA) 和 (rightA, lenA)。接下来看 map 中是否含有 arr[i] + 1,如果有,则说明 arr[i] + 1 所在的连续序列可以与 A 合并,合并后记为 B 序列。利用 map 可以得到 B 序列的长度为 lenB, 最小值记为 leftB,最大值记为 rightB,只在 map 中更新与 leftB 和 rightB 有关的记录,更新成 (leftB, lenB) 和 (rightB, lenB)。

      3. 遍历的过程中用全局变量 max 记录每次合并出的序列的长度最大值,最后返回 max。

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

      具体过程请参看如下代码中的 longestConsecutive 方法:

     1 import java.util.HashMap;
     2 
     3 public class Main {
     4     
     5     public static void main(String[] args) {
     6         int[] arr = {100,4,200,1,3,2};
     7         System.out.println(new Main().longestConsecutive(arr));//4
     8     }
     9     
    10     public int longestConsecutive(int[] arr){
    11         if(arr == null || arr.length == 0) return 0;
    12         int max = 1;
    13         HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
    14         for(int i = 0, len = arr.length; i < len; i++){
    15             if(!map.containsKey(arr[i])){
    16                 map.put(arr[i], 1);
    17                 if(map.containsKey(arr[i] - 1)){
    18                     max = Math.max(max, merge(map, arr[i] - 1, arr[i]));
    19                 }
    20                 if(map.containsKey(arr[i]+1)){
    21                     max = Math.max(max, merge(map, arr[i], arr[i] + 1));
    22                 }
    23             }
    24         }
    25         return max;
    26     }
    27     
    28     public int merge(HashMap<Integer, Integer> map, int less, int more){
    29         int left = less - map.get(less) + 1;
    30         int right = more + map.get(more) - 1;
    31         int len = right - left + 1;
    32         map.put(left, len);
    33         map.put(right, len);
    34         return len;
    35     }
    36     
    37 }
  • 相关阅读:
    how to design a good api and why it matters
    耦合_wiki
    python图形界面:首选Tkinter
    进程间通信:KPIPE
    记 · 今日冬至 · 除了吃还有思考
    【Nodejs】448- 深入学习 Node.js Buffer
    记 · 七言古诗 · 劝学
    【CSS】447- 纯CSS实现简单骨骼动画
    【JS】446- 你不知道的 map
    【前端知乎】445- File FileList 和 FileReader 对象详解
  • 原文地址:https://www.cnblogs.com/zlxyt/p/10575927.html
Copyright © 2011-2022 走看看