Longest Consecutive Sequence & Longest Common Prefix & Search for a Range

(1) Longest Consecutive Sequence

根据[1]: 利用哈希表查找时间复杂度为O(1)的特性,每次循环中可以当前所有序列(min,min+1...max)中的键值<min,max>和<max,min>存在于哈希表中,每次读取新的值都可以更新这两个键值。只需要记录每个区间的最左边的值和最右边的值,中间的不需要考虑。时间复杂度O(n)。

class Solution {
public:
    int longestConsecutive(vector<int> &num) {
        int maxlen=1,n=num.size();
        unordered_map<int,int> hash;
        
        for(int i=0;i<n;i++)
        {
            int cur=num[i];
            if(hash.find(cur)!=hash.end())
                continue;
            hash[cur]=cur;
            int left=cur,right=cur;
            if(hash.find(cur-1)!=hash.end())
                left=hash[cur-1];
            if(hash.find(cur+1)!=hash.end())
                right=hash[cur+1];
            hash[left]=right;
            hash[right]=left;
            maxlen=max(maxlen,right-left+1);
        }
        return maxlen;
    }
};

(2) Longest Common Prefix

根据[2]:这道题很简单,但需要注意减少比较字符的操作次数。2个字符串的最长公共前缀,其长度肯定不会超过最短的字符串的长度,设最短的字符串长度为n,那么只要比较这2个字符串的前n个字符即可。如此得出这2个字符串的最长公共前缀prefix后,再拿prefix作为新的字符串和数组中的下一个字符串比较,方法同上。需要注意的是,如果数组中的某个字符串长度为0,或者求得的当前最长公共前缀的长度为0,就直接返回空字串。

class Solution {
public:
    string longestCommonPrefix(vector<string> &strs) {
        if(strs.size()==0)
            return "";
        string common=strs[0];
        
        for(int i=1;i<strs.size();i++)
        {
            int len=min(common.size(),strs[i].size());
            
            if(len==0)
                return "";
                
            int j;
            for(j=0;j<len;j++)
                if(common[j]!=strs[i][j])
                    break;
                    
            common=common.substr(0,j);
        }
        return common;
    }
};

(3) Search for a Range

用两次二分查找,第一次找左边界,第二次找右边界,处理好每次比较的边界问题和只有两个元素的判断问题。

class Solution {
private:
    int findleftpos(int A[], int n, int target){
        int begin=0,end=n-1,mid;
        
        while(begin<end)
        {
            mid=(begin+end)/2;
            if(A[mid]>=target)
                end=mid;
            else
                begin=mid+1;
        }
        if(A[begin]==target)
            return begin;
        else
            return -1;
    }

    int findrightpos(int A[], int n, int target){
        int begin=0,end=n-1,mid;
        
        while(begin<end)
        {
            mid=(begin+end)/2;
            if(A[mid]<=target)
                begin=mid;
            else
                end=mid-1;
            if(end-begin==1)
                break;
        }
        if(A[end]==target)
            return end;
        else if(A[begin]==target)
            return begin;
        else
            return -1;
    }

public:
    vector<int> searchRange(int A[], int n, int target) {
        vector<int> ret;
        ret.push_back(findleftpos(A, n, target));
        ret.push_back(findrightpos(A, n, target));
        return ret;
    }
};


参考:

[1] http://blog.sina.com.cn/s/blog_6923201d0101bsgg.html

[2] http://blog.csdn.net/zhouworld16/article/details/16882131

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值