1 两数之和

25 篇文章 3 订阅
13 篇文章 0 订阅

虽然只是一道很简单的题,但是也给我很多思考。

刚看到这道题的时候没有仔细思考,直接写了个排序和二分查找,想着对每个数字查找另一个数字会不会出现,复杂度是 O ( n l o g n + n l o g n ) O(nlogn+nlogn) O(nlogn+nlogn),主要训练了一下自己手写快速排序和二分查找。

class Solution {
    void swap(vector<int>& a,vector<int>& b,int i,int j)
    {
        int t=a[i]; a[i]=a[j]; a[j]=t;
        t=b[i]; b[i]=b[j]; b[j]=t;
    }
    void getPovit(vector<int>& a, vector<int>& b,int l,int r)
    {//三者取中得到枢纽
        int mid = (l+r) >> 1;
        if(a[l] < a[mid]) swap(a, b, l, mid);
        if(a[r-1] < a[mid]) swap(a, b, r-1, mid);
        if(a[l] > a[r-1]) swap(a, b, l, r-1);
    }
    void quickSort(vector<int>& a,vector<int>& b, int l,int r)
    {
        if(r-l < 2) return;
        int mid = (l+r) >> 1;
        getPovit(a, b, l, r);
        int povit = a[l];
        int i=l-1; int j=r;
        while(i<j)
        {
            do ++i; while(a[i] < povit);
            do --j; while(a[j] > povit);
            if(i < j) swap(a, b, i, j);
        }
        quickSort(a, b, l, j+1);
        quickSort(a, b, j+1, r);
    }
    int bSearch(vector<int>& a, int l,int r,int x,int now)
    {
        if(r<=l) return -1;
        int mid = (l+r) >> 1;
        if( a[mid] == x && mid != now) return mid;
        if(a[mid] < x) return bSearch(a, mid+1, r, x, now);
        else return bSearch(a, l, mid, x, now);
    }
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> b;
        int n = nums.size();
        for(int i=0; i<n; ++i)
        {
            b.push_back(i);
        }
        quickSort(nums, b, 0, n);
        // sort(nums.begin(), nums.end());
        vector<int> ret;
        for(int i=0; i<n; ++i)
        {
            int tmp = target - nums[i];
            int j = bSearch(nums, 0, n, tmp, i);
            if(-1 != j)
            {
                ret.push_back(b[i]); ret.push_back(b[j]);
                break;
            }
        }
        return ret;
    }
};

上面的做法很傻,稍微聪明一点的做法是排序以后从两边开始查找。这样的复杂度是 O ( n l o g n + n ) O(nlogn+n) O(nlogn+n)的。因为我们求的是两个数字的和,所以对于一个排好序的数组来讲,如果一个数字增大,另一个数字一定减小。因此我们用两个指针,一个指向数组的头部,一个指向数组的尾部,如果出现所求的和就直接返回答案,如果两个指针和比目标小就将前一个指针后移,如果比目标大就把后一个指针前移。这种直觉很容易证明是正确的。

class Solution {
    void swap(vector<int>& a,vector<int>& b,int i,int j)
    {
        int t=a[i]; a[i]=a[j]; a[j]=t;
        t=b[i]; b[i]=b[j]; b[j]=t;
    }
    void getPovit(vector<int>& a, vector<int>& b,int l,int r)
    {//三者取中得到枢纽
        int mid = (l+r) >> 1;
        if(a[l] < a[mid]) swap(a, b, l, mid);
        if(a[r-1] < a[mid]) swap(a, b, r-1, mid);
        if(a[l] > a[r-1]) swap(a, b, l, r-1);
    }
    void quickSort(vector<int>& a,vector<int>& b, int l,int r)
    {
        if(r-l < 2) return;
        int mid = (l+r) >> 1;
        getPovit(a, b, l, r);
        int povit = a[l];
        int i=l-1; int j=r;
        while(i<j)
        {
            do ++i; while(a[i] < povit);
            do --j; while(a[j] > povit);
            if(i < j) swap(a, b, i, j);
        }
        quickSort(a, b, l, j+1);
        quickSort(a, b, j+1, r);
    }
    int bSearch(vector<int>& a, int l,int r,int x,int now)
    {
        if(r<=l) return -1;
        int mid = (l+r) >> 1;
        if( a[mid] == x && mid != now) return mid;
        if(a[mid] < x) return bSearch(a, mid+1, r, x, now);
        else return bSearch(a, l, mid, x, now);
    }
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> b;
        int n = nums.size();
        for(int i=0; i<n; ++i)
        {
            b.push_back(i);
        }
        quickSort(nums, b, 0, n);
        // sort(nums.begin(), nums.end());
        int i = 0, j = n-1;
        while(i < j)
        {
            if(nums[i] + nums[j] == target)
                return vector<int>{b[i], b[j]};
            if(nums[i] + nums[j] < target)
                ++i;
            else 
                --j; 
        }
        return vector<int>();
    }
};

官方给出的题解是通过使用HashMap解决的,发现这样的效率很好,然而我之前没有接触过HashMap,通过一番学习,用HashMap解决了一下。

class Solution {
public:

    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> hashMap;
        unordered_map<int, int>::const_iterator it;
        int n = nums.size();
        hashMap[nums[0]] = 0;
        for(int i=1; i<n; ++i)
        {
            it = hashMap.find(target - nums[i]);
            if(it != hashMap.end())
            {
                return vector<int>{it->second, i};
            }
            hashMap[nums[i]] = i;
        }
        return vector<int>();
    }
};

但是也没有觉得快多少,可能是因为数据比较水看不出来差距吧。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值