leetcode-128-Longest Consecutive Sequence 哈希表

问题

题目:[leetcode-128]

思路

由于没有排序,并且要求在O(N)时间内完成。
考虑哈希表做映射,连续的序列一定在连续的部分命中。当然,如果用c写这个思路可以。但是如果c++用map做,只能是考虑前后两个元素的值是否相差1,从而来判断是否时连续序列。

代码(c++实现)

// c++ version
class Solution {
public:
    int longestConsecutive(std::vector<int>& nums) {

        int sz = nums.size();
        if(!sz)
            return 0;

        std::map< int, bool > mapper;
        for( int i = 0; i < sz; ++i  )
        {
            mapper[nums[i]] = true;
        }

        typedef std::map<int, bool>::const_iterator const_iter;
        const_iter b = mapper.begin();
        const_iter e = mapper.end();

        int max = 0;
        int cnt = 0;
        int pre = b->first - 1;

        while( b != e )
        {
            if( b->first == pre + 1 )
                ++cnt;
            else
            {
                if( cnt > max )
                    max = cnt;
                cnt = 1;
            }   

            pre = b->first; 
            ++b;
        }
        if( cnt > max )
            max = cnt;

        return max;
    }
};

思路1

上面的代码时间复杂度不符合要求:

        std::map< int, bool > mapper;
        for( int i = 0; i < sz; ++i  )
        {
            mapper[nums[i]] = true;
        }

这一段代码相当于一个排序,map查询,插入,删除的复杂度是o(logn),所以,循环之后是o(nlogn)。这里是问题。

看到一个新的思路,也是非常的赞啊。
[Longest Consecutive Sequence leetcode]

还是考虑连续的元素,从某一点开始,分别向元素值-1和元素值+1的地方走,看能走到哪里。如果一个元素之前被走到了,本次没有必要再走,因为之前走到这,如果可以走的更远,之前就可以走了。只需把所有元素放到集合里面就好了。

代码1

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {    
        int sz = nums.size();
        if(!sz) return 0;

        unordered_set<int> mapper(nums.begin(), nums.end());
        int ans = 0;
        for(int i = 0; i < sz; ++i){
            if( mapper.find(nums[i]) != mapper.end() ){
                mapper.erase(nums[i]);

                // move to left
                int left_max = 0;
                int left = nums[i] - 1;
                while( mapper.find(left) != mapper.end() ){
                    mapper.erase(left);
                    left_max++;
                    left--;
                }

                // move to right
                int right_max = 0;
                int right = nums[i] + 1;
                while( mapper.find(right) != mapper.end() ){
                    mapper.erase(right);
                    right_max++;
                    right++;
                }

                int cur = left_max + right_max + 1;
                if(cur > ans) ans = cur;
            }
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值