1. 题目描述:
给一个整数数组,找到两个数使得他们的和等于一个给定的数 target。你需要实现的函数twoSum需要返回这两个数的下标, 并且第一个下标小于第二个下标。注意这里下标的范围是 1 到 n,不是以 0 开头。
注意:你可以假设只有一组答案。
例如:给出 numbers = [2, 7, 11, 15], target = 9, 返回 [1, 2].
2. 思路一:暴力求解
通过双重循环遍历数组中所有元素的两两组合,当出现符合的和时返回两个元素的下标。时间复杂度(o(n^2))。
2.1 写法1(采用数组指针):
int *twoSum(int *nums, int target, int len)
{
int *ret = new int[2];
if(len< 2)
return ret;
for(int i = 0; i <len; i++)
{
for(int j = i+1; j <len; j++)
{
if(nums[i] + nums[j] == target)
{
ret[0] = i + 1;
ret[1] = j + 1;
return ret;
}
}
}
return ret;
}
2.2 写法2(采用向量vector):
vector<int> twoSum(vector<int> nums, int target)
{
vector<int> ret;
for(size_t i = 0; i <nums.size(); i++) //如果这里写成int i,就会出现有符号/无符号不匹配的警告
{
for(size_t j = i+1; j <nums.size(); j++) //如果这里写成int j,就会出现有符号/无符号不匹配的警告
{
if(nums[i] + nums[j] == target)
{
ret.push_back(i + 1);
ret.push_back(j + 1);
}
}
}
return ret;
}
3. 思路二:线性实现-Hash表 O(n)
遍历一次数组,建立一个Map。Map里面 key是元素的值,value是元素原来的下标。然后再从头开始遍历数组,在Map中找target=sum-arr[i]的元素,若存在则返回,否则直至i=len-1说明没有解。最后找到target在arr中的位置即可。时间复杂度O(n)。
3.1 写法1:
vector<int> twoSum(vector<int> &nums, int target)
{
// hmap[i]表示nums中数值为i的下标
map<int, int> hmap;
vector<int> ret;
// 一边循环每个数,一边加入hash表。
for (size_t i = 0; i <nums.size(); i++)
{
//hmap.find(x):获取value为x的键值key
if (hmap.find(target - nums[i]) != hmap.end())
{
// target - nums[i]的下标更小,放在前面
ret.push_back(hmap[target - nums[i]]+1);
ret.push_back(i+1);
return ret;
}
hmap[nums[i]] = i;
}
return ret;
}
3.2 写法2:
vector<int> twoSum(constvector<int> &nums, int target)
{
vector<int> results;
if (nums.size() < 2)
{
return results;
}
map<int , int> hmap;
//插入到hash map
for (size_t i = 0; i <nums.size(); i++)
{
hmap.insert(pair<int, int>(nums[i], i)); //元素值做键值
}
int j;
for (size_t i = 0; i <nums.size(); i++)
{
//hmap.count(x):x在hash map中出现的次数
if (hmap.count(target - nums[i]))
{
j = hmap[(target - nums[i])];
if (j < i)
{
results.push_back(j+1);
results.push_back(i+1);
}
}
}
return results;
}