對於同類問題做了代碼模型:
int i = starting; //頭指針
int j = num.size() - 1; //尾指針
while(i < j) {
int sum = num[i] + num[j];
if(sum == target) {
store num[i] and num[j] somewhere;
if(we need only one such pair of numbers)
break;
otherwise
do ++i, --j;
}
else if(sum < target)
++i;
else
--j;
}
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
• Elements in a quadruplet (a, b, c, d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
• Thesolutionsetmustnotcontainduplicatequadruplets.For example, given array S = {1 0 -1 0 -2 2}, and target = 0.
A solution set is:
(-1, 0, 0, 1)
(-2, -1, 1, 2)
(-2, 0, 0, 2)
關於這道有許多解法:
// 先排序,然後左右夾逼,時間復雜度 O(n^3),空間復雜度 O(1) class Solution {
public:
vector> fourSum(vector& num, int target) {
vector> result;
if (num.size() < 4) return result;
sort(num.begin(), num.end());
auto last = num.end();
for (auto a = num.begin(); a < prev(last, 3); ++a) {
for (auto b = next(a); b < prev(last, 2); ++b) {
auto c = next(b);
auto d = prev(last);
while (c < d) {
if (*a + *b + *c + *d < target) {
++c;
? } else if (*a + *b + *c + *d > target) {
--d;
} else {
result.push_back({ *a, *b, *c, *d });
++c;
--d;
} }
} }
sort(result.begin(), result.end());
result.erase(unique(result.begin(), result.end()), result.end());
return result;
} };
補充: 關於unique()去重的使用,
用一個 hashmap 先緩存兩個數的和, 以及vector
存這兩個數。
在用兩個游標遍歷序列,key = target -v[x]-v[y], 根據 map.find(key), 找出另外兩個數。
時間復雜度,平均 O(n^2),最壞 O(n^4),空間復雜度 O(n^2)
class Solution {
public:
vector > fourSum(vector &sums, int target) {
vector > result;
if (nums.size() < 4) return result;
sort(nums.begin(), num.end());
unordered_map > > cache;
for (int i=0; i(i, j));
}
}
for (int x=0; x > vec = cache[key];
for (int k=0; k
解法三:Multimap
首先要說的是 multimap的概念。
multimap提供了可以一種可以有重復鍵值的STL map類型。其插入方式和map相似,但是由於可以擁有重復鍵值所以在查找方面有些不同
直接找到每種鍵值的所有元素的第一個元素的游標
通過函數:lower_bound( const keytype& x ), upper_bound( const keytype& x ) 可以找到比指定鍵值x的小的鍵值的第一個元素和比指定鍵值x大的鍵值的第一個元素。返回值為該元素的游標。
細節:當到達鍵值x已經是最大時,upper_bound返回的是這個multimap的end游標。同理,當鍵值x已經是最小了,lower_bound返回的是這個multimap的begin游標。
指定某個鍵值,進行遍歷
可以使用上面的lower_bound和upper_bound函數進行游歷,也可以使用函數equal_range。其返回的是一個游標對。游標對pair::first是由函數lower_bound得到的x的前一個值,游標對pair::second的值是由函數upper_bound得到的x的後一個值。
這個算法的 時間復雜度 O(n^2),空間復雜度 O(n^2)
#include
#include
#include
using namespace std;
class Solution {
public:
vector > fourSum(vector& num, int target) {
vector > result;
if (num.size()<4) return result;
sort(num.begin(), num.end());
unordered_multimap> cache;
for (int i=0; i+1first;
pair range = cache.equal_range(x);
for (pair j = range.first; j!=range.second; ++j) {
int a = i->second.first;
int b = i->second.second;
int c = j->second.first;
int d = j->second.second;
if (a != c && a != d && b != c && b != d) {
vector vec = { num[a], num[b], num[c], num[d] };
sort(vec.begin(), vec.end());
result.push_back(vec);
}
}
}
sort(result.begin(), result.end());
result.erase(unique(result.begin(), result.end()), result.end());
return result;
}
};