LeetCode 1. Two Sum

来源:互联网 发布:mac ps如何导入字体 编辑:程序博客网 时间:2024/06/16 13:26

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].

因为题目已经假设只有唯一解,所以不考虑有重复数字的情况。

解法一:
暴力搜索,穷举。时间复杂度O(n^2),空间复杂度O(1)。

解法二:
空间换时间。换个方向想,题目就是求目标值target和其中一个数A的差B在数组中的位置。维护数组中每个元素到索引的映射的最佳方法是什么? 一个哈希表,那么我就利用一个HashMap建立数组中数值和下标的关系。在一次迭代中,先在HashMap中寻找该差值是否存在,如果不存在就把数A及其下标存入HashMap;若是存在,就意味着已经得到最后的结果了。

class Solution {public:    vector<int> twoSum(vector<int>& nums, int target) {        unordered_map<int, size_t> hashMap;        vector<int> result;        for (int i = 0; i < nums.size(); i++)        {            int remain = target - nums[i];            auto findIt = hashMap.find(remain);            if (findIt == hashMap.end())            {                hashMap.insert({ nums[i],i });            }            else            {                result.push_back(findIt->second);                result.push_back(i);            }        }        return result;    }};

时间复杂度、空间复杂度都是O(n)。

解法三:排序+二分查找
先对数组排序。排序后将双指针指向头部与尾部元素,进行迭代。如果双指针指向元素之和大于目标和,则将尾部指针向前移一位,反之则将头部指针向后移一位,直到双指针指向元素之和等于目标和,记录这两个元素的值。
(排序非常直接的就意味着二分搜索。一次查一半,所以刚开始只用到了二分搜索。但是有个问题,二分搜索的步子太大,可能把目标值跳过,那么还要借鉴双指针的全盘扫描的特点。)
存在的问题:
排序的效率?
排序的如何得到正确的索引?
复制一份数组进行排序,然后用原数组查找得到索引。我在此使用的是multiset,利用它本身有序的特性。(以为不含重复数,但是提交时有测试用例不通过)

class Solution {public:    vector<int> twoSum(vector<int>& nums, int target) {        multiset<int> orderSet(nums.cbegin(), nums.cend());        vector<int> rsNum, result;        auto beg = orderSet.begin();        auto end = orderSet.end();        --end;        while (beg != end)        {            if (*beg + *end == target)            {                rsNum.push_back(*beg);                rsNum.push_back(*end);                break;            }            else if (*beg + *end > target)            {                --end;            }            else            {                ++beg;            }        }        for (int i = 0,j=0; i < nums.size(); i++)        {            if (nums[i] == *beg || nums[i] == *end)            {                ++j;                result.push_back(i);                if (j == 2)break;            }        }        return result;    }};  //这道题使用map的话可能会更简洁补上multimap版本:class Solution {public:    vector<int> twoSum(vector<int>& nums, int target) {        multimap <int, size_t> orderMap;        vector<int> result;        for (int i = 0; i < nums.size(); i++)        {            orderMap.insert({ nums[i],i });        }        auto beg = orderMap.begin();        auto end = orderMap.end();        --end;        while (beg != end)        {            if (beg->first + end->first == target)            {                result.push_back(beg->second);                result.push_back(end->second);                break;            }            else if (beg->first + end->first > target)            {                --end;            }            else            {                ++beg;            }        }        return result;    }};

总结综合结果来看,第二种方法是最快的。

原创粉丝点击