力扣 15题 : 三数之和
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不反复的三元组。留神:答案中不能够蕴含反复的三元组。 示例 1:输出:nums = [-1,0,1,2,-1,-4]输入:[[-1,-1,2],[-1,0,1]]解释:nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。留神,输入的程序和三元组的程序并不重要。示例 2:输出:nums = [0,1,1]输入:[]解释:惟一可能的三元组和不为 0 。示例 3:输出:nums = [0,0,0]输入:[[0,0,0]]解释:惟一可能的三元组和为 0 。起源:力扣(LeetCode)链接:https://leetcode.cn/problems/3sum著作权归领扣网络所有。商业转载请分割官网受权,非商业转载请注明出处。
解法1 ,应用哈希表映射
参考:算法 - 哈希表 - 两数之和 与 四数之和
class Solution { public List<List<Integer>> threeSum(int[] nums) { List<List<Integer>> listList = new ArrayList<>(); //Set是为了去除反复的list子集 Set<List<Integer>> s = new HashSet<>(); for (int i = 0; i < nums.length; i++) { int a = nums[i]; Set<List<Integer>> sub = find2Pare(nums, i, 0 - a); s.addAll(sub); } listList.addAll(s); return listList; } /** 把问题化解为两数之和 */ Set<List<Integer>> find2Pare(int[] nums, int start, int target){ Set<List<Integer>> lls = new HashSet<>(); Map<Integer, Integer> map = new HashMap<>(); for (int i = start+1; i < nums.length; i++) { List<Integer> list = new ArrayList<>(); if (map.get(target-nums[i]) != null) { list.add(nums[start]); list.add(nums[i]); list.add(target-nums[i]); Collections.sort(list); lls.add(list); } map.put(nums[i],i); } return lls; }}
解法2 双指针法
class Solution { public List<List<Integer>> threeSum(int[] nums) { // 先做排序 Arrays.sort(nums); List<List<Integer>> lls = new ArrayList<>(); for(int i = 0 ; i < nums.length-2; i++) { // 如果以后数值大于0 ,因为是有序数组,前面的数值都是不可能和为0的,间接返回 if(nums[i] > 0){ return lls; } //对第一个数值去重 if(i > 0 && nums[i] == nums[i-1]){ continue; } int a = nums[i]; int left = i+1; int right = nums.length-1; while(left < right){ if(a + nums[left] + nums[right] == 0){ List<Integer> list = new ArrayList<>(); list.add(a); list.add(nums[left]); list.add(nums[right]); lls.add(list); // 去重在找到第一个元素之后执行 // 对right指针元素去重 while(left < right && nums[right] == nums[right-1]){ right--; } // 对left指针元素去重 while(left < right && nums[left]== nums[left+1]){ left++; } // 找到答案后,双指针膨胀 left++; right--; } else if(a + nums[left] + nums[right] > 0){ right--; }else { left++; } } } return lls; }}