题目描述
- 主要是解决重复的问题:如何去除重复解、在有大量重复解的情况下如何让算法跑得更快
代码 & 解题思路
- 先排序,按照大小顺序来做。
- 思路:固定第一个数,用双指针分别代表另外两个指针
- 去除重复值:对三个数,分别进行去除重复解的行为(见代码注释):
- 第一个数:如果num[i] == num[i-1],那么num[i-1]肯定已经把num[i]的任务给完成了,那么继续进行对num[i]作为第一个数的求解并没有意义,而且可能会带来重复解,因此跳过
- 第二个数:比如说left将要渡过“222”,那么用第一个2作为解时,剩下的两个2就已经没有意义了,于是可以直接跳过后两个2。
- 第三个数:和第二个数的原理一样。
- 注意:要先取得解,再进行跳过重复,直接跳重复,再取值会出问题,或需要更多判断。
class Solution {public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> ans = new ArrayList<List<Integer>>();int len = nums.length;if (len < 3) {return ans;}Arrays.sort(nums);if (nums[0] > 0 || nums[len - 1] < 0) {return ans;}int groupIndex = 0;for (int i = 0; i < len - 2; i++) {if (i > 0 && nums[i] == nums[i - 1]) {continue;}int left = i + 1, right = len - 1;while(left < right){int temp = nums[i] + nums[left] + nums[right];if (temp == 0) {ans.add(new ArrayList<Integer>());ans.get(groupIndex).add(nums[i]);ans.get(groupIndex).add(nums[left]);ans.get(groupIndex).add(nums[right]);groupIndex++;while(left < right && nums[left+1] == nums[left]) ++left;while (right < right && nums[right-1] == nums[right]) --right;left++; right--;}else if (temp > 0) {right--;}else {left++;}}}return ans;}
}
- 时间复杂度:排序O(nlogn) + 遍历固定第一解O(n) * 双指针遍历 O(n),算是O(n2n^2n2)
- 空间复杂度:O(1)
二刷更新
- 之前的代码看看注释就好,写的有点冗余了,不到20行就能解决的事
class Solution {public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> ans = new ArrayList<>();Arrays.sort(nums);for(int i = 0; i < nums.length - 2; i++) {if(i > 0 && nums[i] == nums[i - 1]) continue;int left = i + 1, right = nums.length - 1;while(left < right) {int temp = nums[i] + nums[left] + nums[right];if(temp == 0) {List<Integer> element = new ArrayList<>();element.add(nums[i]);element.add(nums[left]);element.add(nums[right]);ans.add(element);while(left < right && nums[left + 1] == nums[left]) left++;while(left < right && nums[right - 1] == nums[right]) right--;left++; right--;} else if(temp > 0) right--;else left++;}}return ans;}
}