标签:问题 span while 解决 去重 ble 整数 判断 复杂
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
解:首先考虑这样一个问题,求数组内两数之和为0的数对个数。
解法1,枚举i,枚举j,时间复杂度为O(n2)//枚举
解法2,如果数组有序,枚举i,之后j可以通过二分的方法寻找.时间复杂度为O(nlogn)//二分
解法3,在解法2的基础上,如果枚举i时是单调的,那么j也是单调的,排序后可以通过双指针的方法O(n)求解,当然,因为要排序,所以时间复杂度仍为O(nlogn)
解法4:遍历i时,如果数字较小,可以声请一个数组用下标映射的方式O(n)求解,数字较大时也可以用各种数据结构,如二叉查找树,平衡树,map等,时间复杂度O(nlogn)
当问题变成三元组时,枚举第一维i,那么问题就变成了数组内两数之和为-nums【i】的数对个数,上述解法都可以在O(n2logn)的时间复杂度内解决问题,但观察解法3,排序的时间复杂度和查找的时间复杂度是相加的关系,所以在这里解法3的时间复杂度维O(n2+nlogn),总的来说就是O(n2).
因为求出的三元组也是有序的,所以去重就是和上一个求出的三元组不同就加入结果中。
注:这个代码还可以进一步优化,代码中对每个左指针j,右指针k都是从n-1开始,但这里明显满足单调性,对于所有的j,只需要一个右指针k即可。
class Solution { public: vector< vector<int> > threeSum(vector<int>& nums) { vector< vector<int> >s; vector<int>ss; sort(nums.begin(),nums.end()); int n=nums.size(); ss.push_back(-1); ss.push_back(-1); ss.push_back(-1); for(int i=0;i<n-2;i++){ if(nums[i]>0)break; if(i>0&&nums[i]==nums[i-1])continue; int j=i+1,k=n-1; for(; j < k ; j++ ){ while( k>j && nums[i] + nums[j] + nums[k] >= 0){ if(nums[i]+nums[j]+nums[k]==0&&(ss[0]!=nums[i]||ss[1]!=nums[j]||ss[2]!=nums[k])){ ss[0]=nums[i]; ss[1]=nums[j]; ss[2]=nums[k]; s.push_back(ss); } k--; } } } //s.push_back(nums); return s; } };
标签:问题 span while 解决 去重 ble 整数 判断 复杂
原文地址:https://www.cnblogs.com/wz-archer/p/12516099.html