三数之和
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
暴力解法,三重循环找三元组,复杂度O(N3)
class Solution { public: vector<vector<int>> threeSum(vector<int>& nums) { vector<vector<int>> ans; if(nums.size()==3) { if(nums[0]+nums[1]+nums[2]==0) ans.push_back(nums); return ans; } int begin=0; int median=1; int end=2; int size=nums.size(); int count=0; int i=0; vector<int> ans_temp; while(begin<size-2) { if(begin!=median) { while(median<size-1) { if(median!=end) { while(end<size) { count=nums[begin]+nums[median]+nums[end]; if(count==0) { ans_temp.push_back(nums[begin]); ans_temp.push_back(nums[median]); ans_temp.push_back(nums[end]); sort(ans_temp.begin(),ans_temp.end()); for(int j=0;j<ans.size();j++) { if(ans[j]==ans_temp) { ans_temp.clear(); break; } } if(!ans_temp.empty()) { ans.push_back(ans_temp); ans_temp.clear(); } end++; } else end++; } } median++;end=median+1; } } begin++;median=begin+1;end=median+1; } return ans; } };
时间长而且代码臃肿,一点效率都没有。
换个思路,用万能的排序(排序是真好用!!)
class Solution { public: vector<vector<int>> threeSum(vector<int>& nums) { vector<vector<int>> ans; vector<int> ans_part; if(nums.size()==3) { if(nums[0]+nums[1]+nums[2]==0) ans.push_back(nums); return ans; } sort(nums.begin(),nums.end()); int begin;int end;int count=0; for(int i=0;i<nums.size();i++) { begin=i+1;end=nums.size()-1; if(nums[i]>0) break; if(i>1&&nums[i]==nums[i-1]) continue; else { count=0-nums[i]; while(begin<end) { if(nums[begin]+nums[end]<count) { begin++; } else if(nums[begin]+nums[end]>count) { end--; } else { ans_part.push_back(nums[i]); ans_part.push_back(nums[begin]); ans_part.push_back(nums[end]); sort(ans_part.begin(),ans_part.end()); ans.push_back(ans_part); ans_part.clear(); begin++;end--; } } } } sort(ans.begin(),ans.end()); ans.erase(unique(ans.begin(),ans.end()),ans.end()); return ans; } };
好像还行...至于思路,就是排序,找规律。
数组排好序了,从第一个数开始遍历,假设它大于零,那么之后的数都会大于零,就不存在三元数组。
所以只有第一个数不大于0的时候,才进行操作。
怎么操作?举个例子
这有个数组{-5,-3,-2,-1,0,1,2,3,4,5} (排好序的)
第一个数-5,剩下就要找数组内加起来是5的那俩数。这三个数位置不能相同。
那这俩数只能从-3到5这个区间找,所以设置个begin和end表示这个区间(区间有序)。
有了范围,开始找,刚开始begin=-3,end=5,begin+end=2;这说明什么?说明找小了,为了让这个和变大,只能让begin++,因为end--的话,和更小。
好,begin一路++,终于到了0这个位置,和为5,三个数找到了,存储进答案。
下面就要在区间1到4找了。一下子又找到了,再存,2,3也是,继续存,没区间了,结束当前循环。
第二个数成了-3,重复以上步骤.......
因为没有检测区间内重复的元素,所以ans里面有相同的三元组,所以在存之前排序一下,方便最后答案的去重。
--------------------------------------------------------
--------------------------------------------------------
好像还有优化空间,比如去重不用最后单独去,只要在搜索的区间加上重复元素的判定就好了。
class Solution { public: vector<vector<int>> threeSum(vector<int>& nums) { vector<vector<int>> ans; vector<int> ans_part; if(nums.size()==3) { if(nums[0]+nums[1]+nums[2]==0) ans.push_back(nums); return ans; } sort(nums.begin(),nums.end()); int begin;int end;int count=0; for(int i=0;i<nums.size();i++) { begin=i+1;end=nums.size()-1; if(nums[i]>0) break; if(i>0&&nums[i]==nums[i-1]) continue; else { count=0-nums[i]; while(begin<end) { if(nums[begin]+nums[end]<count) { begin++; } else if(nums[begin]+nums[end]>count) { end--; } else { ans_part.push_back(nums[i]); ans_part.push_back(nums[begin]); ans_part.push_back(nums[end]); sort(ans_part.begin(),ans_part.end()); ans.push_back(ans_part); ans_part.clear(); while(begin<end&&nums[begin]==nums[begin+1]) begin++; while(begin<end&&nums[end]==nums[end-1]) end--; begin++;end--; } } } } /* sort(ans.begin(),ans.end()); ans.erase(unique(ans.begin(),ans.end()),ans.end());*/ return ans; } };
posted on 2023-06-19 03:55 WhatAnyWay 阅读(26) 评论(0) 收藏 举报
浙公网安备 33010602011771号