微软面试题: 15. 三数之和 出现次数:3
题目描述:
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?
请你找出所有满足条件且不重复的三元组。 注意:答案中不可以包含重复的三元组。
思路分析:
排序 + 双指针 ,本题考察的重难点在于如何去除重复解。算法流程如下:
1. 特判,对于数组长度 n,如果数组为 null 或者数组长度小于 3,返回 []。
2. 对数组进行排序。
3. 遍历排序后数组。
3.1 若 nums[i] > 0 :因为数组已经排序好,所以后面两个数也是正的 ,不可能有三个数加和等于 0,
直接返回结果。
3.2 对于重复元素:跳过,避免出现重复解。三个数遇到重复元素都要跳过。
3.3 令左指针 L=i+1L=i+1,右指针 R=n-1R=n−1,当 L<RL<R 时,执行循环:
* 当 nums[i]+nums[L]+nums[R]==0nums[i]+nums[L]+nums[R]==0,执行循环,判断左界和右界
是否和下一位置重复,去除重复解。并同时将 L,RL,R 移到下一位置,寻找新的解。
* 若和大于 0,说明 nums[R] 太大,R左移;
* 若和小于 0,说明 nums[L] 太小,L右移;
代码如下:
1 class Solution { 2 public: 3 vector<vector<int>> threeSum(vector<int>& nums) 4 { 5 if(nums.size() < 3) return {}; 6 vector<vector<int>> res; 7 8 const int len = nums.size(); 9 std::sort(nums.begin(),nums.end()); 10 if(nums[0] > 0) return {}; 11 for(int i = 0;i < len - 2;++i) 12 { 13 if(nums[i] > 0) 14 { 15 return res; 16 } 17 int l = i + 1; 18 int h = len - 1; 19 while(l < h) 20 { 21 long int sum = nums[i] + nums[l] + nums[h];//注意整数避免溢出 22 if(sum == 0) 23 { 24 vector<int> triple(3,0); 25 triple[0] = nums[i]; 26 triple[1] = nums[l]; 27 triple[2] = nums[h]; 28 res.push_back(triple); 29 30 while(l+1<h && nums[l] == nums[l+1]) l++; //避免nums[l]作为第二个数重复出现 31 while( h-1 >l && nums[h-1] == nums[h]) h--;//避免nums[l]作为第三个数重复出现 32 l++; 33 h--; 34 } 35 else if(sum > 0) 36 { 37 --h; 38 } 39 else 40 { 41 ++l; 42 } 43 } 44 //避免nums[i]作为第一个数重复出现 45 while(i+1 < len - 2 && nums[i] == nums[i+1]) i++; 46 } 47 return res; 48 } 49 };