Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

题目解释:在一个数组中找寻两个数字的和等于目标值,返回两个数字的索引值,并且有且只有一组解,同一个位置的元素不能用两次

我的错误做法,写出来让自己注意,读者可以忽视
先排序然后使用two pointer的方式去做,会导致index乱了,返回自然会错

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> res;
        sort(nums.begin(), nums.end());
        int l = 0, r = nums.size() - 1;
        while(l < r){
            if(nums[l] + nums[r] == target){
                res.push_back(l);
                res.push_back(r);
                return res;
            }else if(nums[l] + nums[r] < target){
                ++l;
            }else{
                --r;
            }
        }
        return res;
    }
};

这道题直观的做法是O(n^2)的复杂度,二层循环暴力的将每两个数求和,得到结果与target对比。或者外层循环遍历每个数,内层循环找另外一个数。
我仔细想了很久都没有想到怎么优化。后来看了解答,可以优化内层循环找另外一个数,从复杂度为O(n)变为O(1),只用hash即可,key是数组的值,value是index,这样就把总的复杂度降为O(n)。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> res;
        unordered_map<int, int> m;
        for(int i = 0; i < nums.size(); ++i){
            m[nums[i]] = i;
        }
        for(int i = 0; i < nums.size(); ++i){
            //m[target - nums[i]] != i 这是个边界条件,需要注意,嘿嘿,你不加这个条件,submission一下就懂我的意思了
            if(m[target - nums[i]] != 0 && m[target - nums[i]] != i){
                res.push_back(i);
                res.push_back(m[target - nums[i]]);
                return res;
            }
        }
        return res;
    }
};

关键trick:使用hash将遍历的复杂度从O(n)降为O(1)


juji
0 声望0 粉丝

相信技术改变人类,做芯片才能救中国