leetcode128--longest consecutive sequence(java)

[leetcode]longest consecutive sequence(java)

问题描述: 
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(n2)的方法:就是遍历每个元素,查看该元素是否与前面的set中相邻(+-为1),如果是,将其加入到该set中,如果不是,新建一个set。

然后我又想,这里面大量的时间实际上是花在了遍历set中,如果将set变成一个hash表,按查找时间就将为了O(1),此时时间复杂度大概为O(nlogn)。这个想法,比较糟糕的地方是虽然查找时间降为了O(1),但是需要不断的将新元素加入到对应的key set中,这样很不方便实现,而且需要递归的循环下去。

但是在网上看到了其他人的想法,才觉得转换一个思路真的太奇妙了。同样是利用hash表。首先对序列做一个预处理,即将序列中元素添加到hashset中,然后再做一次遍历,如果某元素在hashset中,那么查找它的前一个元素,如果存在,就删除该元素。然后计数加1;

代码如下:

 public int longestConsecutive(int[] nums) {
         HashSet<Integer> sets = new HashSet<Integer>();
         //prepare for process
         for(int i = 0;i<nums.length;i++){
             sets.add(nums[i]);
         }
         int tmp;
         int value,realValue = 1;
         for(int j = 0;j<nums.length;j++){
             tmp = nums[j];
             value = 1;
             if(!sets.contains(tmp))//deleted already
                 continue;


             while(true){
                 if(sets.contains(tmp-1)){
                     value++;
                     sets.remove(tmp-1);
                     tmp = tmp-1;
                 }
                 else
                    break;
             }


             tmp = nums[j];
             while(true){
                 if(sets.contains(tmp+1)){
                     value++;
                     sets.remove(tmp+1);
                     tmp = tmp+1;
                 }else
                    break;
             }


             realValue = (realValue>value)?realValue:value;
         }
         return realValue;
     }


First turn the input into a set of numbers. That takes O(n) and then we can ask in O(1) whether we have a certain number.

Then go through the numbers. If the number x is the start of a streak (i.e., x-1 is not in the set), then test y = x+1, x+2, x+3, ... 

and stop at the first number y not in the set. The length of the streak is then simply y-x and we update our global best with that.

Since we check each streak only once, this is overall O(n). This ran in 44 ms on the OJ

public class Solution {     

public int longestConsecutive(int[] nums) {         

Set<Integer> set = new HashSet<>();         

for(int n : nums) {             

set.add(n);         

}         

int best = 0;         

for(int n : set) {             

if(!set.contains(n - 1)) {  // only check for one direction                 

int m = n + 1;                 

while(set.contains(m)) {                     

m++;                 

}                 

best = Math.max(best, m - n);             

}         

}         

return best;     

}

We will use HashMap. The key thing is to keep track of the sequence length and store that in the boundary points of the sequence. 

For example, as a result, for sequence {1, 2, 3, 4, 5}, map.get(1) and map.get(5) should both return 5.

Whenever a new element n is inserted into the map, do two things:

1、See if n - 1 and n + 1 exist in the map, and if so, it means there is an existing sequence next to n

Variables left and right will be the length of those two sequences, while 0 means there is no sequence and n will be 

the boundary point later. Store (left + right + 1) as the associated value to key n into the map.

2、Use left and right to locate the other end of the sequences to the left and right of n respectively, and replace the value with the 

new length.

Everything inside the for loop is O(1) so the total time is O(n). Please comment if you see something wrong. Thanks.

public int longestConsecutive(int[] num) {
    int res = 0;
    HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
    for (int n : num) {
        if (!map.containsKey(n)) {
            int left = (map.containsKey(n - 1)) ? map.get(n - 1) : 0;
            int right = (map.containsKey(n + 1)) ? map.get(n + 1) : 0;
            // sum: length of the sequence n is in
            int sum = left + right + 1;
            map.put(n, sum);
            
            // keep track of the max length 
            res = Math.max(res, sum);
            
            // extend the length to the boundary(s)
            // of the sequence
            // will do nothing if n has no neighbors
            map.put(n - left, sum);
            map.put(n + right, sum);
        }
        else {
            // duplicates
            continue;
        }
    }
    return res;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值