码迷,mamicode.com
首页 > 其他好文 > 详细

Longest Consecutive Sequence

时间:2015-03-19 21:38:49      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:

https://leetcode.com/problems/longest-consecutive-sequence/

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

For example,
Given [100, 4, 200, 1, 3, 2],
The longest consecutive elements sequence is [1, 2, 3, 4]. Return its length: 4.

Your algorithm should run in O(n) complexity.

解题思路:

这道题的难度在于用O(n)的时间。原来的数组没有排序,如果先排序,必然要花费O(nlogn)的时间,不符合要求。根据经验和直觉,可能是用O(n)的时间去遍历数组,然后借助HashMap,花费O(1)的时间去找某些元素在不在数组中。

按照这样的思路往下想,对于num[i]去寻找它的左侧和右侧邻接的元素,直到在num中不存在,这时更新长度。因为每个数字只能存在于唯一的一个consecutive sequence里,否则这两个sequence就是相连的。

所以,这里拓展过的元素就完全可以从set中删掉了。后面再遍历到的num[j]就可以直接跳过,因为它属于的最长consecutive sequence前面已经找出了。

这样,整体的时间复杂度一定是O(n)。

下面的代码使用了HashMap,同时对num中出现的数字计数。

public class Solution {
    public int longestConsecutive(int[] num) {
        Map<Integer, Integer> numMap = new HashMap<Integer, Integer>();
        for(int i = 0; i < num.length; i++){
            if(numMap.containsKey(num[i])){
                numMap.put(num[i], numMap.get(num[i]) + 1);
            }else{
                numMap.put(num[i], 1);
            }
        }
        
        int longestLength = 0;
        
        for(int i = 0; i < num.length; i++){
            int currentLength = 0;
            int next = num[i];
            while(numMap.containsKey(next) && numMap.get(next) > 0){
                numMap.put(next, numMap.get(next) - 1);
                currentLength++;
                next++;
            }
            
            int previous = num[i] - 1;
            while(numMap.containsKey(previous) && numMap.get(previous) > 0){
                numMap.put(previous, numMap.get(previous) - 1);
                currentLength++;
                previous--;
            }
            longestLength = Math.max(longestLength, currentLength);
        }
        
        return longestLength;
    }
}

后来发现根本没必要,因为一个数字即使出现多次,还是只能出现在一个consecutive sequence里,换成set。

public class Solution {
    public int longestConsecutive(int[] num) {
        Set<Integer> numSet = new HashSet<Integer>();
        for(int i = 0; i < num.length; i++){
            if(!numSet.contains(num[i])){
                numSet.add(num[i]);
            }
        }
        
        int longestLength = 0;
        
        for(int i = 0; i < num.length; i++){
            int currentLength = 0;
            int next = num[i];
            while(numSet.contains(next)){
                numSet.remove(next);
                currentLength++;
                next++;
            }
            
            int previous = num[i] - 1;
            while(numSet.contains(previous)){
                numSet.remove(previous);
                currentLength++;
                previous--;
            }
            longestLength = Math.max(longestLength, currentLength);
        }
        
        return longestLength;
    }
}

再优化,进入循环前就直接判断num[i]在不在set里,不在直接跳过继续!

public class Solution {
    public int longestConsecutive(int[] num) {
        Set<Integer> numSet = new HashSet<Integer>();
        for(int i = 0; i < num.length; i++){
            numSet.add(num[i]);
        }
        
        int longestLength = 0;
        
        for(int i = 0; i < num.length; i++){
            if(!numSet.contains(num[i])){
                continue;
            }
            int currentLength = 0;
            int next = num[i];
            while(numSet.contains(next)){
                numSet.remove(next);
                currentLength++;
                next++;
            }
            
            int previous = num[i] - 1;
            while(numSet.contains(previous)){
                numSet.remove(previous);
                currentLength++;
                previous--;
            }
            longestLength = Math.max(longestLength, currentLength);
        }
        return longestLength;
    }
}

特别警醒的是,开始我的for改成这样,这样如果num[i]不在set里循环就直接退出了,而不是continue。犯了如此基本的错误!

for(int i = 0; i < num.length && numSet.contains(num[i]); i++){
            int currentLength = 0;
            int next = num[i];
            while(numSet.contains(next)){
                numSet.remove(next);
                currentLength++;
                next++;
            }
            
            int previous = num[i] - 1;
            while(numSet.contains(previous)){
                numSet.remove(previous);
                currentLength++;
                previous--;
            }
            longestLength = Math.max(longestLength, currentLength);
        }

 

这就是我的思路。从O(nlogn)到O(n)一般都是这么几个方法。这里使用了空间换时间的思路。

Longest Consecutive Sequence

标签:

原文地址:http://www.cnblogs.com/NickyYe/p/4351445.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!