两数之和
题目描述
给出一个整数数组,请在数组中找出两个加起来等于目标值的数,
你给出的函数twoSum 需要返回这两个数字的下标(index1,index2),需要满足 index1 小于index2.。注意:下标是从1开始的
假设给出的数组中只存在唯一解
例如:
给出的数组为 {20, 70, 110, 150},目标值为90
输出 index1=1, index2=2
示例
输入
[3,2,4],6
输出
[2,3]
题解
方法一:暴力遍历
第一层遍历每一个数字,在遍历的同时,遍历其它数字是否满足target-self
class Solution {
public:
/**
*
* @param numbers int整型vector
* @param target int整型
* @return int整型vector
*/
vector<int> twoSum(vector<int>& numbers, int target) {
vector<int> result;
if(numbers.size() == 0)
return result;
for(int i=0; i<numbers.size(); i++){
for(int j=i+1; j<numbers.size(); j++){
if(target-numbers[i] == numbers[j]){
result.push_back(i+1);
result.push_back(j+1);
break;
}
}
}
return result;
}
};
方法二:Hash算法
在C++中,Hash Table的查询时间是O(1)。第一次遍历,将数组元素和下标建立一个Hash Table。第二次遍历,检查每一个target-self是否在Hash表中存在,注意不能是number[i]本身。
class Solution {
public:
/**
*
* @param numbers int整型vector
* @param target int整型
* @return int整型vector
*/
vector<int> twoSum(vector<int>& numbers, int target) {
vector<int> result;
if(numbers.size() == 0)
return result;
map<int, int> m;
for(int i=0; i<numbers.size(); i++){
m[numbers[i]] = i;
}
for(int i=0; i<numbers.size(); i++){
if(m.find(target-numbers[i]) != m.end() && i != m[target-numbers[i]]){
result.push_back( i + 1 );
result.push_back(m[target-numbers[i]] + 1);
return result;
}
}
return result;
}
};
方法三:部分Hash
一边遍历数组,一边建立Hash表,只建立一部分Hash Table。
class Solution {
public:
/**
*
* @param numbers int整型vector
* @param target int整型
* @return int整型vector
*/
vector<int> twoSum(vector<int>& numbers, int target) {
vector<int> result;
if(numbers.size() == 0)
return result;
map<int, int> m;
for(int i=0; i<numbers.size(); i++){
int complement = target-numbers[i];
if(m.find(complement) != m.end()){
result.push_back(m[complement]+1);
result.push_back(i+1);
break;
} else {
m[numbers[i]] = i;
}
}
return result;
}
};
方法四:排序+双指针
先将原数组复制到一个新的数组当中,对新数组进行排序。利用头指针和尾指针,逐个向中间遍历,找出和为target的两个数。最后在原数组中找到这两个数的下标。
class Solution {
public:
/**
*
* @param numbers int整型vector
* @param target int整型
* @return int整型vector
*/
vector<int> twoSum(vector<int>& numbers, int target) {
vector<int> result;
if(numbers.size() == 0)
return result;
vector<int> temp(numbers);
// 对拷贝的数据从小到大进行排序
sort(temp.begin(), temp.end());
int i = 0;
int j = temp.size() - 1;
int num1 = 0, num2 = 0;
while( i < j) {
// 如果两数之和大于target
if(temp[i]+temp[j] > target) {
j--;
}
// 如果两数之和小于target
else if(temp[i]+temp[j] < target) {
i++;
}
// 如果两数之和等于target
else {
num1 = temp[i];
num2 = temp[j];
break;
}
}
int index1 = -1, index2 = -1;
// 在原数组中查找数字对应的下标
for(int k=0; k<numbers.size(); k++) {
// 首次出现
if(numbers[k]==num1 && index1==-1) {
index1 = k;
continue;
}
if(numbers[k]==num2 && index2==-1) {
index2 = k;
continue;
}
if(index1>-1 && index2>-1)
break;
}
if(index1 < index2) {
result.push_back(index1 + 1);
result.push_back(index2 + 1);
} else {
result.push_back(index2 + 1);
result.push_back(index1 + 1);
}
return result;
}
};