Leetcode 的Array相关题目,Two Sum,3Sum,3Sum Closet,4Sum。都是给定一个整形数组(以vector形式给出),给定一个target number。在数组里找出若干个数,使得和为target number,或者最接近target number。返回满足条件的数组元素或者元素索引。
错误思路:开始想到的思路,排序后,通过两边指针夹逼的形式,排序复杂度为nlogn,两边夹逼复杂度为n。但是这题要求返回元素位置,而排序改变了元素。自然想到使用map,存储元素位置,但是既然使用了map,这题还得nlogn的复杂度,显然不太科学。于是有了下面的思路。
正确思路:通过一个map存储纪录每个元素的位置。扫一遍数组,对每一个元素,计算gap,然后在map中查找,key为gap的位置是否存在。由于在map中执行find操作,时间复杂度为1,故整体时间复杂度为n, Accepted.
class Solution {
public:
vector<int> twoSum(vector<int> &numbers, int target) {
vector<int> ret;
int len = numbers.size();
map<int, int> mp;
for (int i = 0; i < len; ++i)
mp[numbers[i]] = i;
for (int i = 0; i < len; ++i) {
int gap = target - numbers[i];
if (mp.find(gap) != mp.end() && mp[gap] != i) {
ret.push_back(i+1);
ret.push_back(mp[gap]+1);
break;
}
}
return ret;
}
};
class Solution {
public:
int threeSumClosest(vector<int> &num, int target) {
int sum = num[0] + num[1] + num[2];
int gap = abs(sum - target);
int min_gap = gap;
int ret = 0;
sort(num.begin(), num.end());
for (auto a = num.begin(); a != prev(num.end(), 2); ++a) {
auto b = next(a);
auto c = prev(num.end(), 1);
while (b < c) {
sum = *a + *b + *c;
gap = sum - target;
if (abs(gap) <= min_gap) {
ret = sum;
min_gap = abs(gap);
}
if (gap == 0)
return ret;
else if (gap > 0)
c--;
else
b++;
}
}
return ret;
}
};
class Solution {
public:
vector<vector<int> > threeSum(vector<int> &num) {
vector<vector<int> > ret;
if (num.size() < 3)
return ret;
sort(num.begin(), num.end());
for (auto a = num.begin(); a != prev(num.end(), 2); ++a) {
if (a != num.begin() && *a == *(a-1))
continue;
auto b = next(a);
auto c = prev(num.end(), 1);
while (b < c) {
int target= *a + *b + *c;
if (target == 0) {
ret.push_back({*a, *b, *c});
++b;
while (*b == *(b-1))
++b;
--c;
while (*c == *(c+1))
--c;
}
else if (target > 0)
--c;
else
++b;
}
}
return ret;
}
};
class Solution {
public:
vector<vector<int> > fourSum(vector<int> &num, int target) {
vector<vector<int> > ret;
if (num.size() < 4)
return ret;
sort(num.begin(), num.end());
map<int, vector<pair<int, int> > > mp;
for (int i = 0; i < num.size(); ++i)
for (int j = i+1; j < num.size(); ++j) {
int index = num[i] + num[j];
mp[index].push_back(make_pair(i, j));
}
int gap = 0;
for (int i = 0; i < num.size(); ++i) {
for (int j = i+1; j < num.size(); ++j) {
gap = target - num[i] - num[j];
if (mp.find(gap) == mp.end())
continue;
auto tmp = mp[gap];
for (int k = 0; k < tmp.size(); ++k) {
//if (i <= tmp[k].second)
// continue;
//ret.push_back({num[tmp[k].first], num[tmp[k].second], num[i], num[j]});
if (j >= tmp[k].first)
continue;
ret.push_back({num[i], num[j], num[tmp[k].first], num[tmp[k].second]});
}
}
}
sort(ret.begin(), ret.end());
ret.erase(unique(ret.begin(), ret.end()), ret.end());
return ret;
}
};