剑指 Offer 57. 和为s的两个数字

剑指 Offer 57. 和为s的两个数字

 1.暴力循环
运行时间超限。复杂度是O(n^2).
点击查看代码
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> ans(2);
        const int size = nums.size();
        
        for(int p = 0; p < size - 1; p++){
            if(nums[p] + nums[p+1] > target) break;
            for(int q = p + 1; q < size; q++){
                if(nums[p] + nums[q] > target) break;

                if(nums[p] + nums[q] == target){
                    ans[0] = nums[p];
                    ans[1] = nums[q];
                    return ans;
                }
            }
        }
        return ans;
    }
};
2.在暴力的基础上加一点小改进(二分)
复杂度O(nlogn)
执行用时: 208 ms
内存消耗: 98.3 MB
点击查看代码
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> ans(2);
        const int size = nums.size();
        
        for(int p = 0; p < size - 1; p++){
            int left = p + 1, right = size - 1;
            int mid = left + (right - left) / 2;
            while(left <= right){
                if(nums[mid] == target - nums[p]){
                    ans[0] = nums[p];
                    ans[1] = nums[mid];
                    return ans;
                }
                if(nums[mid] < target - nums[p]) 
                    left = mid + 1;
                else
                    right = mid - 1;

                mid = left + (right - left) / 2;
            } 
        }
        return ans;
    }
};

 

3.双指针移动法,复杂度O(n)

看了题解,发现居然有这么妙的方法!

一个升序数组,要找两个数相加得到一个目标数,我们可以从两端开始寻找,设有两个指针p和q,分别指向数组的首端(最小值)和尾端(最大值)。

计算num[p]+num[q](第一个被计算的值是num[0]和num[size - 1],如果这个值小于目标值,那么移动左边的指针(c语言的操作是p++),这样我们舍弃了num[0]+num[size - 2], num[0]+num[size - 3], ... ,num[0]+num[1]这些不可能的解。为什么这些值不可能?num[size - 1] 比所有数组中的元素都要大,它与num[0]相加都小于target,说明在他左边的数与num[0]相加更不可能等于target。理解了这一点,就知道这个双指针算法是如何运行的了。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> ans(2);
        const int size = nums.size();
        
        int p = 0, q = size - 1;
        while(p < q){
            if(nums[p] + nums[q] == target){
                ans[0] = nums[p];
                ans[1] = nums[q];
                return ans;
            }

            if(nums[p] + nums[q] < target) p++;
            else q--;
        }

        return ans;
    }
};
posted @ 2021-09-30 17:11  柚子z  阅读(28)  评论(0)    收藏  举报