3Sum
来源:互联网 发布:java进阶书籍推荐知乎 编辑:程序博客网 时间:2024/06/15 16:34
Given an array S of n integers, are there elements a,b,c inS such thata + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note: The solution set must not contain duplicate triplets.
For example, given array S = [-1, 0, 1, 2, -1, -4],A solution set is:[ [-1, 0, 1], [-1, -1, 2]]
解题思路:
3Sum目前见到的最好的时间复杂度是 o(n2) ,解题思路如下:
1. 先将序列进行排序,时间复杂度为 o(nlogn);
2. 在一个结果中,确定了两个数,那么第三个数也就唯一确定了;
3. 从头开始扫描序列,以当前指针(pos)指向的数字为 target,在序列中找另外两个数使得(*pos+ *left + *right == 0);
4. 假设某一时刻,*pos+ *left + *right == 0 成立,那么对于这个 target 就找到了一个结果;
5. 接下来 left 和 right 指针继续搜索,直到找到对于这个 target 使得等式成立的所有的 left 和 right,然后再从下一个 target 开始;
6. 因为序列中有重复数字,所以当下一个 left (或 right)指针和当前 left (或 right)指针值一样的时候,是否需要以这个 left (或 right)指针再搜索一次?答案是没必要,因为已经确定了两个数,第三个数必然一样,所以直接跳过;
void find(int pos,vector<vector<int>> &ret,vector<int>& nums,int begin,int end)
{
int target = -nums[pos];
int left = begin ;int right = end;
while( left < right )
{
if(target == nums[left] + nums[right]) //找到一个 left 和 right 指针使得等式成立
{
vector<int> tmp;
tmp.push_back(nums[pos]);
tmp.push_back(nums[left]);
tmp.push_back(nums[right]);
ret.push_back(tmp);
while(nums[right] == nums[right-1]) right--;// 跳过和当前 left 值一样的 left 指针,继续寻找其它满足等式的指针
while(nums[left] == nums[left+1]) left++; // right 指针同理
}
if(target < nums[left] + nums[right])right--; // 根据数列有序的特点,没找到 left 和 right 的时候移动相应的指针
else left++;
}
}
7. 因为序列中有重复数字,所以当下一个数字和当前 target 值一样时,是否应该再以这个 target 搜索一次?答案是没必要,因为当一个 target 搜索完成后,序列中所有满足等式的指针都已被找到,所以直接跳过;
while(i < nums.size()-2)
{
find(i,ret,nums,i+1,nums.size()-1);//搜索完一个 target ( i 就是 pos 指针)
while(i < nums.size()-2 && nums[i] == nums[i+1]) i++;//直接跳过和当前 target 值一样的 target
i++;
}
8. 对于新的 target , 此时 left 指针要从头开始扫描序列么?如果从头开始扫描,假设在新的 target 之前找到了一个新的 left 使得等式成立,那么说明之前这个新的 left 作为 target的时候,也可以找到这个新的 target 作为它的 left 使得等式成立;或者假设在新的 target 之前没有找到一个新的 left 使得等式成立,那么说明之前这个新的 left 作为 target,找到这个新的 target 作为它的 left 指针的时候也不能使得等式成立,所以综上 left 指针没必要从头开始扫描序列,而是从新的 target 的下一个位置处开始,因为如果从头开始扫描,无论是否能够找到,其实都已经在之前的 target 的扫描过程中搜索过了;
while(i < nums.size()-2)
{
find(i,ret,nums,i+1,nums.size()-1);//搜索完一个 target ( i 就是 pos 指针) // left 指针从target 的下一个位置开始
while(i < nums.size()-2 && nums[i] == nums[i+1]) i++;//直接跳过和当前 target 值一样的 target
i++;
}
完整代码:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <stack>
using namespace std;
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ret;
if(nums.size() == 0 || nums.size() == 1 || nums.size() == 2)
return ret;
sort(nums.begin(),nums.end());
int i = 0;
while(i < nums.size()-2)
{
find(i,ret,nums,i+1,nums.size()-1);
while(i < nums.size()-2 && nums[i] == nums[i+1]) i++;
i++;
}
return ret;
}
private:
void find(int pos,vector<vector<int>> &ret,vector<int>& nums,int begin,int end)
{
int target = -nums[pos];
int left = begin ;int right = end;
while( left < right )
{
if(target == nums[left] + nums[right])
{
vector<int> tmp;
tmp.push_back(nums[pos]);
tmp.push_back(nums[left]);
tmp.push_back(nums[right]);
ret.push_back(tmp);
while(nums[right] == nums[right-1]) right--;
while(nums[left] == nums[left+1]) left++;
}
if(target < nums[left] + nums[right])right--;
else left++;
}
}
};
void main()
{
vector<int> nums ;
int tmp;
while(cin >> tmp)nums.push_back(tmp);
Solution s;
s.threeSum(nums);
}
- Two Sum && 3 Sum
- 【Leetcode】3Sum (Sum)
- 3Sum 3Sum Closest 4Sum
- 3Sum & 3Sum Closest & 4Sum
- 3sum、3Sum closet、 4sum
- 3Sum, 3Sum Closest, 4 Sum
- leetcode 2 sum 3sum 4sum
- 2Sum 3Sum 4Sum
- Leetcode 2SUM-3SUM-4SUM
- Leetcode-2sum,3sum,4sum
- leetcode 2 sum & 3 sum & 4 sum
- 3Sum
- 3SUM
- 3-sum
- 3Sum
- 3Sum
- 3Sum
- 3Sum
- Release版本只在iOS9.2及以下闪退
- PAT 1005. 继续(3n+1)猜想
- ARM微处理器第二弹:寄存器
- Pytorch学习笔记(六)
- MySQL:MySQL日期数据类型、MySQL时间类型使用总结
- 3Sum
- Android Studio错误代码不提示问题解决
- 前端js和后端PHP函数的调用
- 文件上传
- PCI 总线初始化
- spring-boot-starter-data-rest 资源暴露策略设置 RepositoryDetectionStrategies
- TCP协议的三次握手和四次释放详解
- 基于easyui的富文本编辑器的实现
- 海航集团连续两年获评“中国企业社会责任最佳责任企业”奖 不可能债务违约