1、三数之和(算法题)
题目:
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
思路:
题述所知,该题目主要实现的两个大的功能。其一,令三个数的和为0;其二,这三个数所组成的三元组不能重复。
对于第一功能,可以使用三次循环的方法,即第一次循环固定一个元素,进行第二遍循环固定第二个元素,最后进行第三遍循环,寻找使三个元素的和为零的元素。这个思路是正确的,但却存在一定的缺陷,即不能完美解决不重复的功能。综上,在此基础之上需要进一步的优化。
对于第二功能,如果需要实现的话就需要通过比较当前元素是否与之前出现过的元素相等来判断是否进行下一步,但这无疑又加大了时间复杂度。此时,我们可以通过数列排序,这时每次只需要比较当前元素与前一个元素是否相等即可。如果相等则直接判断下一个元素,如果不相等则进行寻找元素来使元素的和为0。
除此之外,对于第二次循环遍历和第三次循环遍历,我们可以合并为一次整体的循环遍历。此时,通过双指针的方法,分别指向第一个所固定的元素的后一个元素和最后一个元素。我们只需要比较当前值与所期望的值,即第一个固定的元素的相反数的大小。此时我们固定第二个元素,将第二个元素与第三个元素的和与期望值进行比较,如果大于则减小第三个元素的下标值(减小第三个元素的值),直到两个指针相遇或两数之和不再大于目标值。此时,之所以不考虑小于target的情况则详见代码注释。
代码:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
//第一遍循环
for(int first = 0; first < n; first++){
//去重
if(first > 0 && nums[first - 1] == nums[first]){
continue;
}
int third = n - 1;
int target = -nums[first];
//第二遍循环
for(int second = first + 1; second < n; second++){
if(second > first + 1 && nums[second] == nums[second - 1]){
continue;
}
//此时之所以不判断小于target的情况,是因为如果小于target则通过外层循环来增加second
//如果两数之和大于target则一定需要减小third的值,因为整个数组是升序排序的
while(second < third && nums[second] + nums[third] > target){
third--;
}
if(second == third){
break;
}
if(nums[second] + nums[third] == target){
ans.push_back({nums[first], nums[second], nums[third]});
}
}
}
return ans;
}
};
相关方法:
(1)sort函数
语法:
sort(begin, end, cmp),cmp参数可以没有,如果没有默认升序排序;如果降序排序,则为sort(end, begin);cmp参数为指定排序的方式。
(2)push_back()函数
作用:
将新元素加到vector的最后面,当前最后一个元素的下一个元素。
语法:
push_back(par),参数为要插入的值。
拓展:
pop_back() //移除最后一个元素
clear() //清空所有元素
empty() //判断vector是否为空,如果返回true为空
erase() // 删除指定元素