前言
因为是非常经典的面试题,所以记录一下
(另一道也非常经典的面试题:两数之和)
一、题目
二、方法
排序+双指针
排序是关键的一步,因为这样所有取出来的三元组都能够满足
ak<ai<aj(其中,k<i<j)
排序是为了方便去除重复的情况。
算法思路:
- 首先进行特判。根据题目给出的例子,nums长度小于3的情况,直接返回空数组[ ];
- 对数组进行排序;
- 对排好序的数组进行遍历:
(1)若nums[i]>0:因为数组已经排好序了,如果nums[i]>0,那么后面的元素肯定也大于零,那么肯定不会有和为0的三元组,所以直接返回结果res;
(2)判断当前元素是否存在重复值,如果重复的话就跳过,防止重复情况的发生;
(3)指定双指针:
左指针:l=i+1; 右指针:r=nums.size()-1;
当l<r时,执行循环:
<1>如果nums[i]+nums[l]+nums[r]>0,说明nums[r]太大了,所以应该让右指针往左移到下一个,但是应该判断一下此时是否符合l<r,并且r现在指向的元素和将要左移指向的元素是否相同,相同则跳过,继续左移并判断;
<2>如果nums[i]+nums[l]+nums[r]<0,说明nums[l]太小了,所以应该让左指针往右移到下一个,但是应该判断一下此时是否符合l<r,并且l现在指向的元素和将要右移指向的元素是否相同,相同则跳过,继续右移并判断;
<3>如果nums[i]+nums[l]+nums[r]=0,则将这个三元组放进res,然后将l指针往右移,并且判断l<r是否符合,l指向的元素是否重复,重复则跳过,r指针往左移,判断l<r是否符合,r指向的元素是否重复,重复则跳过。如果不重复,则指针后移或前移,然后重新判断nums[i]+nums[l]+nums[r]的值。
C++语言代码如下:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
//排序
sort(nums.begin(), nums.end());
//如果nums是空数组或者长度小于3,则返回[]也就是空数组
if(nums.size()<3)return res;
for(int i=0; i<nums.size(); i++){
//如果nums[i]大于0,那么之后的数字都是大于0的,肯定不会符合题意了
if(nums[i]>0)break;
//去重复
if(i>0 && nums[i]==nums[i-1])continue;
int l = i+1;
int r = nums.size()-1;
while(l<r){
int sum = nums[i]+nums[l]+nums[r];
if(sum>0){
while(l<r && nums[r]==nums[r-1])r--;
r--;
continue;
}
if(sum<0){
while(l<r && nums[l]==nums[l+1])l++;
l++;
continue;
}
if(sum==0){
res.push_back({nums[i],nums[l],nums[r]});
while(l<r && nums[r]==nums[r-1])r--;
while(l<r && nums[l]==nums[l+1])l++;
r--;
l++;
}
}
}
return res;
}
};
C语言代码如下:
在这里插入代码片
举个栗子:
step1:
step2:
step3:
step4:
step5:
step6:
step7:
step8:
step9:
step10:
step11:
step12:
一些总结
关于*returnSize 和 *returnColumnsize的解释
C语言解法中传入的参数涉及*returnSize 和 *returnColumnsize,之前没有接触过,所以记录一下需要注意的地方。
C语言默认模板为:
具体可详细参考:
(这个跟刷题有点关系但是其实跟算法思想关系不大,但是不了解的话又容易不通过)