(LeetCode 面试经典 150 题 ) 15. 三数之和 (排序+双指针)
题目:15. 三数之和
思路:排序+双指针,时间复杂度0(n^2+nlogn)。
先将数组nums升序排序,方便去重和使用双指针。第一层for循环来枚举第一位数,后面使用双指针来找到第二个、第三个数即可,细节看注释。
C++版本:
class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {// 先将数组nums升序排序,方便去重和使用双指针int n=nums.size();sort(nums.begin(),nums.end());// 答案vector<vector<int>> v;// 遍历第一个数for(int i=0;i<n-2;i++){// 如果和前一个数重复,跳过if(i!=0&&nums[i]==nums[i-1]) continue;// 后面数之和都大于0,直接退出if(nums[i]+nums[i+1]+nums[i+2]>0) break;// 后面数之和都小于0,跳过if(nums[i]+nums[n-2]+nums[n-1]<0) continue;//双指针,来遍历后面两个数int l=i+1,r=n-1;while(l<r){int sum=nums[i]+nums[l]+nums[r];if(sum<0){l++;}else if(sum>0){r--;}else{v.push_back({nums[i],nums[l],nums[r]});l++;r--;// 避免重复的数while(l<n){if(nums[l]==nums[l-1]) l++;else break;}// 避免重复的数while(r>=l){if(nums[r]==nums[r+1]) r--;else break;}}}}return v;}
};
JAVA版本:
class Solution {public List<List<Integer>> threeSum(int[] nums) {int n=nums.length;Arrays.sort(nums);List<List<Integer>> v=new ArrayList<>();for(int i=0;i<n-2;i++){if(i!=0&&nums[i]==nums[i-1]) continue;if(nums[i]+nums[i+1]+nums[i+2]>0) break;if(nums[i]+nums[n-2]+nums[n-1]<0) continue;int l=i+1,r=n-1;while(l<r){int sum=nums[i]+nums[l]+nums[r];if(sum<0){l++;}else if(sum>0){r--;}else{v.add(Arrays.asList(nums[i],nums[l],nums[r]));l++;r--;while(l<n){if(nums[l]==nums[l-1]) l++;else break;}while(r>=l){if(nums[r]==nums[r+1]) r--;else break;}}}}return v;}
}
GO版本:
func threeSum(nums []int) [][]int {n:=len(nums)slices.Sort(nums)v:=[][]int{}for i:=0;i<n-2;i++ {if i!=0 && nums[i]==nums[i-1] {continue}if nums[i]+nums[i+1]+nums[i+2]>0 {break}if nums[i]+nums[n-2]+nums[n-1] <0 {continue}l,r:=i+1,n-1for l<r {sum:=nums[i]+nums[l]+nums[r]if sum<0 {l++}else if sum>0 {r--}else{v=append(v,[]int{nums[i],nums[l],nums[r]})l++r--for l<r {if nums[l]!=nums[l-1] {break}l++}for l<r {if nums[r]!=nums[r+1] {break}r--}}}}return v
}