题目:
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
题目要求很明确,给出一组整型数组(没有顺序, 有可能有重复的值,并且有可能有负数),找到两个其中的数,使得它们的和为所给的target。顺序输出那两个数的下标。每组数组有且只有一组答案。
一开始看了题目就直接写了两个for循环搞定,代码如下。然后兴高采烈的提交代码,结果就悲剧了。
系统给的错误是Time Limit Exceeded,所用的测试数组元素个数为10000,两个for循环算完花都谢了。
vector<int> twoSum(vector<int> &numbers, int target) {
vector<int> indexs;
vector<int> res;
bool flag = true;
for (int i=0; i<numbers.size()-1 && flag; i++)
{
for (int j=i+1; j<numbers.size(); j++)
{
if(numbers[i] + numbers[j] == target)
{
res.push_back(i+1);
res.push_back(j+1);
flag = false;
break;
}
}
}
return res;
}
分析2:
这个问题看似要找两个数,但是可以转换一下变成找一个数的问题。而对一个元素个数很大的数组,要快速找到其中的某个数,还是得用HashMap。于是有了第二种算法,代码如下:
vector<int> twoSum(vector<int> &numbers, int target) {
vector<int> res(2,0);
unordered_map<int, int> numbersMap;
for(int i=0; i<numbers.size(); i++)
numbersMap[numbers[i]] = i;
unordered_map<int, int>::const_iterator iter = numbersMap.end();
for (int i=0; i<numbers.size(); i++)
{
int minus = target - numbers[i];
iter = numbersMap.find(minus);
if (iter != numbersMap.end() && iter->second != i)
{
if (i < iter->second)
{
res[0] = i+1;
res[1] = iter->second + 1;
}
else
{
res[0] = iter->second + 1;
res[1] = i + 1;
}
}
}
return res;
}
unordered_map<int, int>的Key和Value都是整型数据,我以numbers中的数据作为Key,然后以相应的下标作为Value, 创建并初始化了一个map。这里有一个问题是,numbers中有可能有相同的值,相同的值在map中的Key一样,但是对应的Value不一样。unordered_map内部应该有处理这种冲突了,所以不用担心这个问题。
还需要注意的是,当找到要找的数(minus)时,一定要根据下标判断一下是否跟number[i]是同一个数,如果下标相同,则还没找到。
if (iter != numbersMap.end() && iter->second != i)
下面是完整代码,包括测试:
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
vector<int> twoSum(vector<int> &numbers, int target)
{
vector<int> res(2,0);
// 创建并初始化HashMap,以numbers的每个值作为key,而value是相对应的下标。
// numbers中的值有可能相同,但相同的值对应的下标不同。
unordered_map<int, int> numbersMap;
for(int i=0; i<numbers.size(); i++)
numbersMap[numbers[i]] = i;
unordered_map<int, int>::const_iterator iter = numbersMap.end();
for (int i=0; i<numbers.size(); i++)
{
// 求差并以差值为key查找
int minus = target - numbers[i];
iter = numbersMap.find(minus);
if (iter != numbersMap.end() && iter->second != i) // 看是否找到了,而且还要判断找到的是否是同一个值
{
if (i < iter->second)
{
res[0] = i+1;
res[1] = iter->second + 1;
}
else
{
res[0] = iter->second + 1;
res[1] = i + 1;
}
}
}
return res;
}
int _tmain(int argc, _TCHAR* argv[])
{
int target = 9;
vector<int> numbers;
numbers.push_back(2);
numbers.push_back(7);
numbers.push_back(11);
numbers.push_back(15);
vector<int> res = twoSum(numbers, target);
// 测试结果
for (int i=0; i<res.size(); i++)
cout << res[i] << " ";
cout << endl;
return 0;
}
对于HashMap其实了解不多,要认真研究一下才行!