您的位置:首页 > 其它

[leetcode]18. 4Sum

2016-05-25 00:11 295 查看

题目地址

https://leetcode.com/problems/4sum/

题目大意

有一组数
a
,给定一个目标数
target
,从
a
找出4个数,使得
sum(a[i], a[j], a[p], a[q]) = target
。输出所有这样的4个数的组合。并且组合中的数要从小到大排列。

解题思路

这是一系列的题目,叫做
k sum
。求解
k sum
的方法,可以通过求解
2sum
来推导。

2sum

求解
2sum
想到的最暴力的方法是遍历所有组合,然后找出符合要求的。这时的时间复杂度为
O(n^2)


有没有更简单的方法呢。显然是有的。我们可以先将数组排序。然后使用两个指针,分别指向数组的头和尾然后使用如下的方法来遍历这个数组。

int left = 0;
int right = n - 1;
while (left < right) {
int sum = a[left] + a[right];
if (sum == target) {
record_left_right(left, right);
} else if (sum < target) {
left++;
} else {
right--;
}
}


这样,我们的时间复杂度就为
O(nlogn) + O(n) = O(nlogn)


推广到K sum

对于所有的
k sum
,我们都能把它退化为
k-1 sum
。方法是,选定一个数
a[i]
,然后计算
new_target = target - a[i]
k - 1 sum
问题。

这样,我们可得
k sum(k >= 3)
的时间复杂度为
O(nlogn) + O(n^(k - 1)) = O(n^(k - 1))


源码

class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> result;
int num_num = nums.size();
if (num_num < 4) {
return result;
}

sort(nums.begin(), nums.end());

set<vector<int>> tmpres;

for (int outer = 0; outer < num_num; ++outer) {
for (int inner = outer + 1; inner < num_num; ++inner) {

int left = inner + 1;
int right = num_num - 1;

while (right > left) {

int tmp_result = nums[outer] + nums[inner] + nums[left] + nums[right];
if (tmp_result == target) {
vector<int> tmp;
tmp.push_back(nums[outer]);
tmp.push_back(nums[inner]);
tmp.push_back(nums[left]);
tmp.push_back(nums[right]);
--right;
++left;
bool duplicate = false;

tmpres.insert(tmp);

} else if (tmp_result < target) {
++left;
} else {
--right;
}
}
}
}

auto it = tmpres.begin();
for(; it != tmpres.end(); it++)
result.push_back(*it);
return result;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode