vector<vector<int>> leedcode15::easy_threeSum(vector<int>& nums)
{
/**
* 巧妙解法:其中有一些剪枝优化的思想
* 1、先对给定的数组进行从小到大排序
* 如: 1, 2, -1, -3, 0, 3
* 排序:-3, -1, 0, 1, 2, 3
* 2、从排序后数组中第一个元素开始固定,
*如固定-3,然后设置一个指针p1指向-1,设置另一个指针p2指向3。
* 1)若*p1 + *p2 = 3,则返回这三个数值,然后两个指针同时移动,
*若只移动一个指针,结果必定是重复的三个数值,或者不相等。
* 2)若*p1 + *p2 < 3, 则将p1指针向右移动,若*p1 + *p2 > 3则反之。
* 3)注意:若指针移动后的值与没有移动的值相同,则要跳过。
* 依次固定直到固定的元素大于0
*/
//0 0 0 0 0 0 0 0 0
//0 1 2 3 4 5 6 7 8
//-5 -5 -4 -4 -4 -2 -2 -2 0 0 0 1 1 3 4 4
//vector<int> vec_result;
vector<vector<int>> result; //设置一个容器的容器用来盛放结果
if (nums.size() < 3) return result; //非常重要的代码,边界条件传入数组小于3则直接返回
sort(nums.begin(), nums.end()); //对传入的容器内的元素进行排序。
//for(int i = 0; i < nums.size(); i++)
int i = 0; //固定第一个元素
while(i != nums.size() - 2) //固定第一个元素,开始总循环,直到固定到倒数第三个元素
{
/**
*总循环的第一步判断:
* 1)i > 0:这里固定的第一个元素无需与前一个固定元素进行判断相等
* 2)nums[i] == nums[i - 1]:固定的后一个元素与前一个元素相等,则跳过
*/
if(i > 0 && (nums[i] == nums[i - 1])) i++;
/**
*若总循环不需要跳过,则执行具体的比较代码
*/
else
{
if(nums[i] > 0) break; //若固定的元素大于0,则直接结束本次循环
int target = 0 - nums[i]; //设置固定元素的相反数
if(nums[i] <= 0) //若固定元素小于0,则执行具体代码
{
int m = i + 1; //设置指针m,指向固定元素的后面一位元素
int n = nums.size() - 1;//设置指针n,指向最后一位元素
while(m < n) //进行循环判断(只有m < n才能遍历所有)
{
if(nums[m] + nums[n] == target) //判断,若满足条件
{ /**
* 里层判断:1)m > 0, n < (nums.size() - 1)这是对固定元素的是否重复的判断
* 若两个指针均移动一位后,与之前两个元素都相等,则两个指针都要移动,
* 若只移动一个则一定不会满足相等条件,或者重复
*/
if(m > 0 && nums[m] == nums[m - 1] && n < (nums.size() - 1) && nums[n] == nums[n + 1])
{
++m;
--n;
}
else
{
//vec_result.insert(vec_result.begin(), nums[i]);
//vec_result.insert(vec_result.begin() + 1, nums[m]);
//vec_result.insert(vec_result.begin() + 2, nums[n]);
//vec_result.erase(vec_result.begin() + 3, vec_result.end());
result.push_back({nums[i], nums[m], nums[n]});
//vec_result.erase(vec_result.begin(), vec_result.end());
++m;
--n;
}
}
if(nums[m] + nums[n] < target) ++m; //并列判断条件
if(nums[m] + nums[n] > target) --n; //并列判断条件
}
}
i++; //移动固定元素
}
}
//sort(result.begin(), result.end());
//result.erase(unique(result.begin(), result.end()), result.end());
return result;
}