leetcode 1. Two Sum

来源:互联网 发布:数控车床编程例子 编辑:程序博客网 时间:2024/05/14 06:23

leetcode 1. Two Sum

Question

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.

Example

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

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

问题

给定一个整数数组和一个目标整数,返回两个索引值,使得这两个索引对应的两个数组元素的和为目标数组。假设只有唯一解。

分析

首先想到的肯定是常规的两重遍历法,时间复杂度为O(n2);
倒排索引法(inverted index):创建一个map,把数组的value作为key,把数组的key作为value。一次遍历数组nums,通过倒排索引的map查找key为target - nums[i]的value j,则[i, j]即为所求索引对;
首尾指针夹逼法:首先将数组排序(注意要保存原索引),然后首尾两个指针分别向中间移动,直到找到符合条件的指针对。

代码

两重遍历法:

vector<int> twoSum(vector<int>& nums, int target) {        vector<int> ret;        for (int i = 0; i < nums.size(); i++)        {            for (int j = i + 1; j < nums.size(); j++)            {                if (nums[i] + nums[j] == target)                {                    ret.push_back(i);                    ret.push_back(j);                    return ret;                }            }        }        return ret;    }

倒排索引法:

vector<int> twoSum(vector<int>& nums, int target) {        vector<int> ret;        map<int, int> numsMap;        for (int i = 0; i < nums.size(); i++)        {            if (numsMap.find(target - nums[i]) == numsMap.end())            {                numsMap[nums[i]] = i;            }            else            {                ret.push_back(numsMap[target - nums[i]]);                ret.push_back(i);                break;            }        }        return ret;    }

首尾夹逼法:

    struct Compare    {        bool operator() (const pair<int, int> &lhs, const pair<int, int> &rhs)        {            return lhs.second < rhs.second;        }    };    vector<int> twoSum(vector<int>& nums, int target) {        vector<int> ret;        vector<pair<int, int>> numsPair;        for (int i = 0; i < nums.size(); i++)        {            numsPair.push_back({i, nums[i]});        }        sort(numsPair.begin(), numsPair.end(), Compare());        int beg = 0;        int end = nums.size() - 1;        while(beg < end)        {            int sum = numsPair[beg].second + numsPair[end].second;            if (sum == target)            {                ret.push_back(numsPair[beg].first);                ret.push_back(numsPair[end].first);                break;            }            else if (sum < target)            {                beg++;            }            else if (sum > target)            {                end--;            }        }        return ret;    }

复杂度再分析

网上看到很多网友说倒排索引法的时间复杂度是O(n),我觉得是不对的,应该是O(nlogn)。假设当前进行到第i次循环,numsMap中有i-1个元素,STL map的find操作是O(logn)的复杂度,那么整个循环的复杂度应该是log1 + log2 + log3 + … + log(i-1) >= (i - 1)log(i-1)。
至于首尾夹逼法,由于有排序,所以复杂度也是O(nlogn)。

总结

当需要用value来定位key的时候,需要用倒排索引;
有序序列可以用二分法、首尾指针夹逼法快速查找元素。

0 0
原创粉丝点击