描述
给一个整数数组,找到两个数使得他们的和等于一个给定的数 target。
你需要实现的函数twoSum
需要返回这两个数的下标, 并且第一个下标小于第二个下标。注意这里下标的范围是 0 到 n-1。
样例
给出 numbers = [2, 7, 11, 15]
, target = 9
, 返回 [0, 1]
.
挑战
Either of the following solutions are acceptable:
- O(n) Space, O(nlogn) Time
- O(n) Space, O(n) Time
解题思路
我一看这个O(nlogn) Time就开心了,一看就是二分查找嘛,结果给自己弄坑里去了:)
因为二分查找需要排序,排序会改变原始坐标,所以需要copy一个原始函数,判断copy函数的时候还要注意不能搞成相同的位置,踩完坑了之后终于过了。。后来随手一搜发现大家都hashMap O(n)搞定。我哈希函数学太差,只是感觉这个不是O(n)空间能搞定的,等我搞清楚hashMap咋回事再回来改。
代码
class Solution {
public:
/**
* @param numbers: An array of Integer
* @param target: target = numbers[index1] + numbers[index2]
* @return: [index1, index2] (index1 < index2)
*/
int binary_search(vector<int> &numbers, int target, int low){
int high = numbers.size()-1;
int res = -1;
while(low <= high){
int mid = (low + high)/2;
//cout << mid << endl;
if(target == numbers[mid]){
return mid;
}
else if(target < numbers[mid]){
high = mid -1;
}
else{
low = mid + 1;
}
}
return res;
}
void copy(vector<int> &numbers, vector<int> ©_num){
for(int i=0; i<numbers.size(); i++){
copy_num.emplace_back(numbers[i]);
}
}
int get_prev_pos(vector<int> &numbers, vector<int> ©_num, int pos, int start){
int num = numbers[pos];
cout << num << endl;
for(int i=0; i<copy_num.size(); i++){
if(i == start) continue;
if(copy_num[i] == num) return i;
}
return -1;
}
vector<int> twoSum(vector<int> &numbers, int target) {
// write your code here
vector<int> copy_num;
copy(numbers, copy_num);
sort(numbers.begin(), numbers.end());
int size = numbers.size();
vector<int> res;
for(int i=0; i<size; i++){
int target_num = target - numbers[i];
int pos = binary_search(numbers, target_num, i+1);
if(pos != -1){
int first = get_prev_pos(numbers, copy_num, i, -1);
int second = get_prev_pos(numbers, copy_num, pos, first);
if(first < second){
res.emplace_back(first);
res.emplace_back(second);
}
else{
res.emplace_back(second);
res.emplace_back(first);
}
return res;
}
}
return res;
}
};