一、问题描述
Description: Given an array of integers, find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.
You may assume that each input would have exactly one solution.
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
给定一个整数数组和一个目标数,从数组中找出两个数,使它们的和等于目标数。twoSum()
函数找出这样的两个数,并返回它们在数组中的位置(从1开始),注意不是返回下标,下标是从0开始。
假设每组测试用例都存在这样的两个数。
二、解题报告
1. 解法一:O(n)
这里的思路是:遍历数组,依次将每个元素插入一个缓存区。每次都对当前元素nums[i]
进行判断:
- 若
target - nums[i]
不在缓冲区,将nums[i]
加入缓冲区; - 若
target - nums[i]
在缓冲区,则当前元素和缓冲区中找到的那个元素就是要求的两个数,返回它们的位置即可。
为了关联每个元素的值和它们的位置,我们使用multimap<int, int>
容器,key表示元素的值,value表示元素的位置。① 由于元素的值可能重复,所以我们使用multi
。②为了提高查找效率,可以使用unordered_multimap
,该容器基于 hash table 。
下面上代码:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_multimap<int, int> m; // 缓冲区
unordered_multimap<int, int>::iterator it;
vector<int> result;
for(int i=0; i<nums.size(); ++i)
{
int another = target - nums[i];
it = m.find(another);
if(it == m.end()) // 没找到,加入缓冲区
{
m.insert(make_pair(nums[i], i+1));
}
else
{
result.push_back(it->second);
result.push_back(i+1);
break;
}
}
return result;
}
};
2. 解法二:O(nlogn)
解法二的思路就是先排序,然后利用头尾指针找到两个数使得他们的和等于target。
bool cmp(pair<int,int> &p1, pair<int,int> &p2) {
return p1.first < p2.first;
}
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<pair<int,int>> v; // <值,下标>
for(int i=0; i<nums.size(); ++i)
v.push_back(make_pair(nums[i], i+1));
sort(v.begin(), v.end(), cmp); // 排序
int i = 0; // 头指针
int j = v.size()-1; // 尾指针
vector<int> res;
while(i < j) {
int sum = v[i].first + v[j].first;
if(sum == target) {
res.push_back(v[i].second);
res.push_back(v[j].second);
break;
}
else if(sum < target)
++i;
else
--j;
}
sort(res.begin(), res.end());
return res;
}
};
LeetCode答案源代码:https://github.com/SongLee24/LeetCode