三数之和,leetCode热题100,C++实现
题目来源:leetCode
15. 三数之和 - 力扣(LeetCode)
解法
class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>> result;int n = nums.size();if(n<3) return result;sort(nums.begin(),nums.end());//排序if (nums[0] > 0 || nums[n-1] < 0) return result; // 全正数或全负数,直接返回for(int i = 0;i<n-2;i++){//优化,如果当前nums[i]>0,则后续值均大于0,和必定不为0,提前结束if(nums[i]>0 || nums[n-1]<0) break;//跳过重复的数字,i>0是防止数组越界,如果i=0,则i-1为-1if(i>0 && nums[i] == nums[i-1]) continue;int left = i+1,right = n-1;int target = -nums[i];while(left < right){int sum = nums[left]+nums[right];if(sum == target)//找到了{result.push_back({nums[i], nums[left], nums[right]});while(left<right && nums[left] == nums[left+1]) left++;//跳过重复值while(left<right && nums[right] == nums[right-1]) right--;//跳过重复值后指向的是最后一个重复值left++;right--;}else if (sum < target) {//和小了,需要增大while (left < right && nums[left] == nums[left+1]) left++;//跳过重复值left++;} else {//和大了,需要减小while (left < right && nums[right] == nums[right-1]) right--;//跳过重复值right--;}}}return result;}
};
代码看着比较长,因为是多次优化后得到的(主要优化去重,所以while循环很多),但逻辑其实很简单,我们对数组进行排序,然后选择左侧元素,接着在右边的区间里使用双指针法,当有符合的条件,我们将他加入数组即可
比如数组最初,我们有一个nums[i],此时就需要一个负的nums[i]相加,我们在右侧区间找两数之和为-nums[i]的数字即可,遇到重复的数字我们进行跳过,我们设sum为nums[left]+nums[right],如果等于nums[i]就是我们的结果之一,如果小于,和小了,需要增大和让其等于nums[i],大于同理,代码去重比较彻底,遇到重复的值基本都会跳过,大家结合代码注释看即可。