首页 > 代码库 > leetcode: 3Sum
leetcode: 3Sum
题目:给定一个数组和一个目标值,返回所有不重复的3元组,每个元组的和等于目标值,且元组中,各元素按飞递减顺序。
先对其进行排序,在利用2sum,在2sum中,要求和为0,这里可以将数组中的元素的相反数作为和,找到另外两个数,那么三者的和为0。
在2sum中,经过排序后,总的时间复杂度是排序算法的复杂度占主导O(NlogN),在查找时是遍历数组,复杂度为O(n)。那么在3sum中,首先进行排序,复杂度为O(NlogN), 在查找时,我们令排序后的数组中的每个元素的相反数作为目标和去调用2sum,整体的复杂度是O(n^2)。当然4sum也可以来调用3sum了,等待。
这里虽然确定了复杂度,但是在具体的实现的时候,需要去瘦身,跳过不可能的解,或者是重复的解,否则超时,真超时。
优化基于两个方面,一种是基于数组元素本身可能存在的重复;一种是基于题目的要求,不要重复的结果。
我们在处理了当前元素后(将当前元素的相反数作为和),若是下个元素与这个元素相同,那么就不用再去算了;在处理到 i 元素时,i 以前的元素我们也不用考虑了,比如 {1,2,1, 4},要求结果为 4 。 处理 第一个1 时,我们会找到 2,1. 返回{1,1,2},在考虑到第二个1时,得到的一种解还是{1,1,2}, 是一种组合,不是排列。
vector<vector<int> > reUnion; void twoSum(vector<int> &numbers, int start, int target){ if(numbers.size() == 0 || start >= numbers.size() - 2) return; int small = start; int large = numbers.size() - 1; while (small < large) { int sum = numbers[small] + numbers[large]; bool equal = false; if(sum == target) { vector<int> re(3); re[0] = numbers[start - 1]; re[1] = numbers[small]; re[2] = numbers[large]; reUnion.push_back(re); equal = true; } //skip the multiple if(sum < target || equal) do { ++small; } while (small < large && numbers[small] == numbers[small + 1]); if(sum > target || equal) do { --large; } while (large > small && numbers[large] == numbers[large - 1]); } } vector<vector<int> > threeSum(vector<int> &num) { if(num.size() < 3) return reUnion; sort(num.begin(),num.end()); for (int i = 0; i < num.size() - 2; ++i) { twoSum(num, i + 1, -num[i]); while(i + 1 < num.size() && num[i + 1] == num[i]) ++i; } return reUnion; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。