Longest Consecutive Sequence

题目中要求时间复杂度O(n),所以不能通过简单的排序来解决问题,但我试了下先排序再做的效果,很不错,至少以很漂亮的速度AC了,哈哈。。。

先贴一个“投机取巧”先排序的版本,要注意去除重复元素的影响

class Solution {
public:
    int longestConsecutive(vector<int> &num) {
        int n=num.size();
        if(n==0)
        {
            return 0;
        }
        sort(num.begin(),num.end());
        vector<int>::iterator itr=unique(num.begin(),num.end());
        n=itr-num.begin();
        vector<int> dp(n,1);
        int max=1;
        for(int i=1;i<n;++i)
        {
            if(num[i]==(num[i-1]+1))
            {
                dp[i]=dp[i-1]+1;
            }
            if(dp[i]>max)
            {
                max=dp[i];
            }
        }
        return max;
    }
};

思来想去还是没有找到O(n)的解法,最终参考了论坛大神的解法,算是学习了一下,贴上大神的代码:

int longestConsecutive(vector<int> num) {
    unordered_map<int,int> m;
    int ret = 0;
    for(auto & n: num){

        //it is in the middle of some consecutive sequence OR we can say it is already visited earlier
        //therefore it does not contribute to a longer sequence
        if(m[n]) continue; 

        //we cannot find adjacent sequences to n, therefore it is a single element sequence by itself
        if(m.find(n-1) == m.end() && m.find(n+1) == m.end()){ // 
            ret = max(ret, m[n] = 1);
            continue;
        }

        //found a sequence at n+1
        //you may wonder what if the sequence at n+1 contains element n?
        //It it contains n, when we add the length by 1 using m[n+1]+1, it is wrong, right?
        //However it is not possible, because if sequence at n+1 contains n, m[n] must have been visited earlier
        //we checked that using if(m[n]) continue; here m[n] is not yet visited;
        //therefore sequence m[n+1] is always on right side, we can safely extend the length by 1
        if(m.find(n-1)==m.end()){ 

            //we want to maintain the TWO boundaries of the sequence
            //the new length of the sequence is the original length m[n+1] incremented by 1
            //left boundary m[n] = m[n+1] +1;
            //right boundary m[n+m[n+1]] = m[n+1]+1;
            //why n+m[n+1]? it is equal to m[n+1]+(n+1)-1 
            //meaning the old left boundary n+1 plus the old length m[n+1] minus 1
            //e.g. for sequence 3,4,5,6 m[3] = 4, and right boundary 6 = 3+m[3]-1 (here n+1 == 3);
            int r = m[n] = m[n+m[n+1]] = m[n+1]+1;
            ret = max(ret, r);
            continue;
        }

        //this is similar to the above case just extend to the right
        if(m.find(n+1)==m.end()){
            int r = m[n] = m[n-m[n-1]] = m[n-1]+1;
            ret = max(ret,r);
            continue;
        }

        //here, we found both sequences at n+1 and n-1, for reasons we explained,
        //the sequences have no overlap.
        //Now, we just need to add the length of current element n (which is 1) to both left and right boundaries
        //the new length will be :  
        //old length of left sequence (m[n-1]) + old length of right sequence (m[n+1]) + 1
        //We also need to mark m[n] as visited, here we can either mark it with 1 or the new length;
        int r = m[n-m[n-1]] = m[n+m[n+1]] = 1+ m[n+1]+ m[n-1];
        m[n] = 1; //basically we just need to mark m[n] as any non-zero number
        // or we can write
        //int r = m[n] = m[n-m[n-1]] = m[n+m[n+1]] = 1+ m[n+1]+ m[n-1];
        ret = max(ret,r);
    }
    return ret;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值