15_三数之和
/** * ★☆ 启发:可以参考完题解:官网的答案,看不懂,★ 可以结合高赞的答案,或者评论区其他详细的解说 */ package 数组; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; /** * https://leetcode-cn.com/problems/3sum/ * * @author Huangyujun * * 其实主要思路:在于避免重复: 然后:通过 第一层循环,暂时确定下来第一个数后,target 更新一下 * 接下来的此情况(只是需要避免重复,然后与57_和为s的连续正数序列 的思考角度一致了): 就是滑动窗口的通用框架2啦 * 细节:有值传入,特殊值的判断,如果数组为 null 或者数组长度小于 33,返回 []。 * 处理:对数组进行排序,优化比较查找 * 细节2:第一个值:nums[i] > 0 ,而数组又已经经过了排序,则直接结束了 */ public class _15_三数之和 { public List<List<Integer>> threeSum(int[] nums) {// 总时间复杂度:O(n^2) List<List<Integer>> ans = new ArrayList<>(); if (nums == null || nums.length <= 2) return ans; Arrays.sort(nums); // O(nlogn) for (int i = 0; i < nums.length - 2; i++) { // O(n^2) if (nums[i] > 0) break; // 第一个数大于 0,后面的数都比它大,肯定不成立了 if (i > 0 && nums[i] == nums[i - 1]) continue; // 去掉重复情况 int target = -nums[i]; /** * 注意避免重复的滑动窗口的通用框架2啦 */ int left = i + 1, right = nums.length - 1; while (left < right) { //① 结果 == target if (nums[left] + nums[right] == target) { ans.add(new ArrayList<>(Arrays.asList(nums[i], nums[left], nums[right]))); // 现在要增加 left,减小 right,但是不能重复,比如: [-2, -1, -1, -1, 3, 3, 3], i = 0, left = 1, // right = 6, [-2, -1, 3] 的答案加入后,需要排除重复的 -1 和 3 left++; right--; // 接下来的 while (left < right && nums[left] == nums[left - 1]) 和 while (left < right && nums[right] == nums[right + 1]) 都是避免重复 while (left < right && nums[left] == nums[left - 1]) left++; while (left < right && nums[right] == nums[right + 1]) right--; } else if (nums[left] + nums[right] < target) { //② 结果 < target left++; } else { // nums[left] + nums[right] > target //③ 结果 > target right--; } } } return ans; } } // //public List<List<Integer>> threeSum(int[] nums) { // int a = 0; // int b = 1; // int c = 2; // Arrays.sort(nums); // List<List<Integer>> ans = new ArrayList<List<Integer>>(); // if(nums.length < 3) return ans; // int len = nums.length; // int target = 0; // while (a <= nums.length - 3) { // if(nums[a] > 0) break; // //判断nums[a] 是否与前一个相同,相同则重复,跳过 // if(a > 0 && nums[a] == nums[--a]) continue; // target -= nums[a]; // while (c <= len) { // if (nums[b] + nums[c] == target) { // // 记录 // List<Integer> list = new ArrayList<Integer>(); // list.add(nums[a]); // list.add(nums[b]); // list.add(nums[c]); // ans.add(list); // while (b < c && nums[b] == nums[b - 1]) { // b++; // } // while (b < c && nums[c] == nums[c - 1]) { // cleft++; // } // } // a++; // b++; // c = b + 1; // } // return ans; //}