很经典的一道题。一个数组里找两个数相加等于目标值,输出两个数的位置。
实在没想出来什么好办法,有一个思路,按照快排的想法,每次选取一个随机标记,分为左右,然后根据标记和目标值的大小比较,缩小搜索范围,最终时间复杂度是O(nlogn).
不过想想就觉得很难code出来,所以最终还是采用了排序再二分查找的办法,很普通的算法。
另外要注意两个相同的数也要处理。
class Solution {
public:
vector<int> twoSum(vector<int> &numbers, int target) {
vector<int> res;
vector<int> indexes;
int i;
for (i = 0; i < numbers.size(); i++)
{
indexes.push_back(numbers[i]);
}
sort(numbers.begin(), numbers.end());
int n = numbers.size();
for (i = 0; i < n; i++){
int num = numbers[i];
int left = i+1, right = n-1, mid = (left + right) / 2 ;
int tmpsum = -1;
while (left <= right){
tmpsum = num + numbers[mid];
if (tmpsum == target)break;
else if (tmpsum < target)left = mid + 1;
else right = mid - 1;
mid = (left + right) / 2;
}
if (tmpsum == target){
int a = -1, b = -1;
for (int j = 0; j < n; j++){
if (indexes[j] == numbers[i] || indexes[j] == numbers[mid]){
if (a < 0)a = j + 1;
else{
b = j + 1; break;
}
}
}
res.push_back(a);
res.push_back(b);
break;
}
}
return res;
}
};
另一种用map的解法我也试过,但是时间花得多的多。而且用的是unordered_map,不知道是不是编译器的原因。
下面是别人的类似代码,写得不太漂亮:
vector<int> twoSum(vector<int> &numbers, int target) {
int index1 = 0, index2 = 0;
// Special Case: target = a + a, cannot be solved by map
for (int i = 0; i < numbers.size(); ++i) {
if (numbers[i] == target / 2) {
if (index1 == 0) index1 = i + 1; else index2 = i + 1;
}
}
if (index1 > 0 && index2 > 0) {
vector<int> result { index1, index2 };
return result;
}
unordered_map<int, int> m;
for (int i = 0; i < numbers.size(); ++i) m[numbers[i]] = i + 1;
for (int i = 0; i < numbers.size(); ++i) {
if (m[target - numbers[i]] && m[target - numbers[i]] != i + 1) {
index1 = m[numbers[i]];
index2 = m[target - numbers[i]];
break;
}
}
if (index1 > index2) { index1 ^= index2; index2 ^= index1; index1 ^= index2; }
vector<int> result { index1, index2 };
return result;
}