题目参见这里 https://leetcode.com/problems/longest-consecutive-sequence/

这个题目我感觉很难,看了半天别人写的答案,才明白个所以然。下面的代码是我自己的改编,写的好像很复杂的样子,主要也是为了方便自己理解,耐着性子看完,应该就理解了。

【个人分析】:

  题目难度主要是要求O(N)完成。本来最自然的想法是先排序然后再去扫一遍得到结果,可是这样,明显就是O(NlgN)。怎么样从NlgN 提高到O(N)呢?  ==> 空间换时间,空间从O(1) 变成 O(N)  ==> 变成O(N)的空间的话,首推哈希表  ==> 如果是用哈希表的话,用序列中的数字做 map 中的 key 是比较自然的想法,所以问题就集中到了,用什么来做 map 中的 value 上来。

【代码注释】:

    上面的主线基本只能推进到那里了,剩下的就是对题目本身的挖掘。我在这里用的是类似动态规划里面常用的前缀、后缀的那种思路。新建了一个类 Bound 来作为 map 中的value , (当然可以不用新建类,直接用一个 list 来做。新建一个类是为了写起来清楚)。对于map中的一个值 num, 它对应的value 是Bound, Bound.maxRangeAsLeftBound 是说,到目前为止,以 num 作为一个连续序列的左边界的所有可能中最长的那个,maxRangeAsRighgBound类似的道理。举个例子,如果有 map[3] = {maxRangeAsLeftBound = 2, maxRangeAsRightBound=3}, 那么就是说存在连续序列【3,4】,和连续序列【1,2,3】

   这个算法的精髓,我个人认为,在于只抓一个范围的两头,对于在范围里面的数字置之不理。什么意思? 假设数组是【4,3,1,2】 ,在依次处理完4,3,1之后,我们要处理2,加入2之后,整个数组中,最长的连续序列将变成,【1-4】。此时,我们只需要更新1,和 4在map中对于的value, 而对于3,这个数夹在1-4之间,对于它在map中的value,我们不必再费神去更新。

  为什么? 你想嘛,假设后面出现了一个更长的序列,是以3 作为左边界,即 maxRange = [3,...], 那么让1做这个范围的边界岂不是可以得到一个更长的【1,2,3...]? 同样的道理,如果maxRange = [...3], 那么让4作为这个范围的右边界,范围也会变得更长。所以,我们不会再用到 3 在map 中对应的 value, 所以也就不用再去更新它了。

  正是因为这样,整个算法的复杂度才是O(N), 如果对于任意一个数字,都要去更新range中所有数字对应的value,那么复杂度就会变成平方。

【实际例子】:  int[] nums = {4,1,3,2}, int resultExpected = 4

数组中的数字(num) 左邻数字是否存在 以num作为右边界的最长序列 右邻数字是否存在 以num作为左边界的最长序列 包含该数字的最长连续序列 更新 更新后Map
4 3存在吗?  否 [4] 5存在吗? 否 [4] [4] U [4] = [4] m[4]={l:1,r:1} {4:{l:1,r:1}}
1 0存在吗? 否 [1] 2存在吗?否 [1] [1] U [1] = [1] m[1]={l:1,r:1}

{4:{l:1,r:1}}

{1:{l:1, r:1}}

3 2存在吗?  否 [3]  4存在吗? [3,4] [3] U [3,4] = [3,4] 

m[3]={l:2,r:1}

m[4].r = 2

m[3].l = 2

(3,4是包含3的最大范围的两端边界)

{4: {l: 1, r: 2}}

{1:{l: 1, r: 1}}

{3:{l: 2,r: 1}}

2 1存在吗? [1,2]  3存在吗? 是  [2,3,4]  [1,2]U[2,3,4] = [1,2,3,4] 

m[2]={l:3,r:2}

m[4].r = 4

m[1].l = 4

(1,4是包含2的最大范围的两端边界)

{4: {l: 1, r: 4}}

{1:{l:4,r:1}},

{3:{l:2,r:1}},

{2:{l:3,r:2}}

 public class Solution {
public int longestConsecutive(int[] nums) {
int result = 0;
Map<Integer, Bound> rangeMap = new HashMap<Integer, Bound>(); for (int i = 0; i < nums.length; i++) {
int num = nums[i];
if ( !rangeMap.containsKey(num) ) {
int maxRangeToThisNumber = 1;
int maxRangeFromThisNumber = 1;
// can this number be a right boundary of a range ?
if (rangeMap.containsKey(num - 1)) {
maxRangeToThisNumber += rangeMap.get(num - 1).maxRangeAsRightBound;
}
// can this number be a left boundary of a range?
if (rangeMap.containsKey(num + 1)) {
maxRangeFromThisNumber += rangeMap.get(num + 1).maxRangeAsLeftBound;
}
int maxRangeIncludeThisNumber =
maxRangeToThisNumber + maxRangeFromThisNumber - 1; // update range map
Bound bound = new Bound(maxRangeFromThisNumber, maxRangeToThisNumber);
rangeMap.put(num, bound); // num is not the right boundary of max range including num
if (maxRangeFromThisNumber != 1) {
// update the range of number at the right bound
int rightEnd = maxRangeFromThisNumber + num - 1;
Bound boundRight = rangeMap.get(rightEnd);
boundRight.maxRangeAsRightBound = maxRangeIncludeThisNumber;
rangeMap.put(rightEnd, boundRight);
}
if (maxRangeToThisNumber != 1) {
int leftEnd = num - maxRangeToThisNumber + 1;
Bound boundLeft = rangeMap.get(leftEnd);
boundLeft.maxRangeAsLeftBound = maxRangeIncludeThisNumber;
rangeMap.put(leftEnd, boundLeft);
} // update global max
result = Math.max(result, maxRangeIncludeThisNumber);
}
} return result;
} public class Bound {
public int maxRangeAsRightBound = 0;
public int maxRangeAsLeftBound = 0;
public Bound(int _maxRangeAsLeftBound, int _maxRangeAsRightBound) {
maxRangeAsLeftBound = _maxRangeAsLeftBound;
maxRangeAsRightBound = _maxRangeAsRightBound;
}
} }

[Leetcode] Longest Consecutive Sequence 略详细 (Java)的更多相关文章

  1. LeetCode——Longest Consecutive Sequence

    LeetCode--Longest Consecutive Sequence Question Given an unsorted array of integers, find the length ...

  2. [LeetCode] Longest Consecutive Sequence 求最长连续序列

    Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...

  3. LeetCode: Longest Consecutive Sequence 解题报告

    Longest Consecutive Sequence Given an unsorted array of integers, find the length of the longest con ...

  4. [leetcode]Longest Consecutive Sequence @ Python

    原题地址:https://oj.leetcode.com/problems/longest-consecutive-sequence/ 题意: Given an unsorted array of i ...

  5. [LeetCode] Longest Consecutive Sequence

    Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...

  6. LeetCode: Longest Consecutive Sequence [128]

    [题目] Given an unsorted array of integers, find the length of the longest consecutive elements sequen ...

  7. Leetcode: Longest Consecutive Sequence && Summary: Iterator用法以及ConcurrentModificationException错误说明

    Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...

  8. LeetCode—Longest Consecutive Sequence

    题目描述: Given an unsorted array of integers, find the length of the longest consecutive elements seque ...

  9. [Leetcode] Longest consecutive sequence 最长连续序列

    Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...

随机推荐

  1. develop process

    -f Option is dangerous, make sure that only do this on your own branch # When you starting coding at ...

  2. Webpack: 为Web开发而生的模块管理器[转]

    Webpack: 为Web开发而生的模块管理器 原文地址:http://hanjianwei.com/2014/09/10/webpack-package-manager-for-web/ 10 Se ...

  3. JAVA_build_ant_sed

    1.简介 sed是非交互式的编辑器.它不会修改文件,除非使用shell重定向来保存结果.默认情况下,所有的输出行都被打印到屏幕上. sed编辑器逐行处理文件(或输入),并将结果发送到屏幕.具体过程如下 ...

  4. iOS中设置导航栏标题的字体颜色和大小

    iOS中设置导航栏标题的字体颜色和大小,有需要的朋友可以参考下. 在平时开发项目的时候,难免会遇到修改导航栏字体大小和颜色的需求,一般使用自定义视图的方法,其实还存在一种方法. 方法一:(自定义视图的 ...

  5. 使用Query 进行空值(empty)校验

    效果如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...

  6. Android 网络通信框架Volley的简单使用

    Volley是Android平台上的网络通信库,能使网络通信更快,更简单,更健壮. Volley提供的功能: JSON,图像等的异步下载: 网络请求的排序(scheduling) 网络请求的优先级处理 ...

  7. qt鼠标事件总结(坐标,跟踪,点击判断)

    1.QMouseEvent中的坐标QMouseEvent中保存了两个坐标,一个是全局坐标,当然另外一个是局部坐标.全局坐标(globalPos())即是桌面屏幕坐标(screen coordinate ...

  8. rdesktop命令连接Win7远程桌面

    1. 开启远程服务,并添加远程桌面用户: 2. 远程桌面开启失败,如果远程桌面开启失败,到服务控制台里面去找到“remote desktop services”依赖的几个服务,是不是被禁用了.都开启一 ...

  9. Linux企业级项目实践之网络爬虫(14)——使用正则表达式抽取HTML正文和URL

    正则表达式,又称正规表示法.常规表示法(英语:Regular Expression,在代码中常简写为regex.regexp或RE),计算机科学的一个概念.正则表达式使用单个字符串来描述.匹配一系列符 ...

  10. windows对象总结

    这篇文章是对windows对象的总结,在winows编程中,windows对象,句柄是一个基本概念,理解这些概念有助于后面的windows编程学习.文章的形式还是以解答问题的方式来组织. 注:在文中, ...