您的位置:首页 > 编程语言 > C语言/C++

[LeetCode] 3Sum分析与C/C++解法

2016-03-08 21:23 344 查看

前言

3Sum算是LeetCode最经典的十几道题之一了,据说在面试中出现的频率相当高。所以在这里花点篇幅讨论一下此题。

题目

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

Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:

Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)

The solution set must not contain duplicate triplets.

For example, given array S = {-1 0 1 2 -1 -4},

A solution set is:

(-1, 0, 1)

(-1, -1, 2)

题目大意就是在给定的数组中找出三个数字,使得它们的和为零。把所有满足此条件且不重样的一组数字塞进vector< vector >里并返回之。

分析

这道题算是当年那个TwoSum的进阶版,关于TwoSum这道题,我已经写了一篇博文,其中有这么一句话,

没有多想,这种与数组的某个特征值相关的问题,先排个序总是没错的。可以先从小到大sort一下,然后给扔两个指针到数组头尾,开始寻找满足要求的值。

这种排序+双指针的思路,可以说是屡试不爽,对于此题亦然。

我们可以先把给定的数组sort一下,然后先进入一层index循环,由于题目要求三个数的和为零,所以我们可以设置一个目标值target,使之等于最外层遍历的元素的相反数,即-nums[i],然后此题就转化为了一个在剩下的元素中寻找两个数的和等于target的TwoSum问题。

这里还需要注意两点:

题目要求找出所有满足条件的unique的三个数的组合,所以我们需要设置过滤机制。

当target值本身小于零的时候,即nums[i]是一个大于零的数。由于数组已经是从小到大排序了的,对于这种情况,nums[i]之后的元素都会比零大,此时显然无法组成一个和为零的组合。

具体见代码。

代码

class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
std::sort(nums.begin(),nums.end());
int n = nums.size();
for (int i = 0; i < n; i++) {
int target = -nums[i], front = i + 1, back = n - 1;
if (target < 0) break;
while (front < back) {
int sum = nums[front] + nums[back];
if (sum < target) front++;
else if (sum > target) back--;
else {//已经找到了一组答案
vector<int> tri(3,0);
tri[0] = nums[i], tri[1] = nums[front], tri[2] = nums[back];
ans.push_back(tri);//将这组数字放进答案

while (front < back && nums[front] == tri[1]) front++;//寻找下一个不同的数字
while (front < back && nums[back] == tri[2]) back--;//寻找下一个不同的数字
}
}
while (i + 1 < n && i + 2 < n && nums[i+1] == nums[i])
i++;//寻找下一个不同的数字
}
return ans;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode