3Sum
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
- Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
- The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4}, A solution set is: (-1, 0, 1) (-1, -1, 2)
之前Leetcode出过两个数相加的题目,这次是三个数,要求找出一个乱序数组中满足要求的三个数,要求这三个数之和为0,可能有若干个三元组,注意每个三元组不能重复,且每个三元组内的三个数字为非降序排列的。
解题思路:分析一下三元组的特点,有以下两种情况:1、三个数全为零;2、一定有一个正数,一个负数,还有一个可为正数可为负数可为零。所以,首先把该数组进行升序排列,排列后分为三种情况讨论:1、第一个数字为零;2、最后一个数字为零;3、第一个数字小于零且最后一个数字大于零。除了以上三种情况的其他情况均无解,下面来分析以上三种情况:
第一种情况:第一个数字为零,判断第二、三个数字是否也为零,是则有解且唯一:[[0,0,0]]。
第二种情况:最后一个数字为零,判断倒数第二、倒数第三个数字是否也为零,是则有解且唯一:[[0,0,0]]。
第三种情况:最常见的情况,头小于零,尾大于零。由于一定有一个正数、一个负数,所以设置两个指针i和j指向头和尾,零减去这两个数之和得到第三个数,判断第三个正负性,若是非负数且比j指向的正数小,则开始从j-1向左搜索,直到负数出现;若第三个数是负数且比i指向的负数大,则开始从i+1向右搜索,直到非负数出现。如此循环,再将j自减1,重新循环,直到j指向的数变为非正数,此时将i自加1,再将j重新指向最后一个数字,重新循环遍历。
java代码实现:public static List<List<Integer>> threeSum(int[] nums) { Arrays.sort(nums); System.out.println(Arrays.toString(nums)); List<List<Integer>> fi = new ArrayList<List<Integer>>(); int i=0,j=nums.length-1; if(nums.length>2){ if(nums[i]==0) if(nums[1]==0&&nums[2]==0){ List<Integer> sig = new ArrayList<Integer>(); sig.add(0); sig.add(0); sig.add(0); fi.add(sig); System.out.println(sig.get(0)+"/"+sig.get(1)+"/"+sig.get(2)); return fi; } if(nums[j]==0) if(nums[j-1]==0&&nums[j-2]==0){ List<Integer> sig = new ArrayList<Integer>(); sig.add(0); sig.add(0); sig.add(0); fi.add(sig); System.out.println(sig.get(0)+"/"+sig.get(1)+"/"+sig.get(2)); return fi; } int temp_i=nums[i]; int temp_j=nums[j]; while(nums[i]<0&&nums[j]>0){ while(nums[j]>0){ int res = -(nums[i]+nums[j]); if(res>=0&&res<=nums[j]){ for(int key=j-1;nums[key]>=0;key--){ if(nums[key]==res){ List<Integer> sig = new ArrayList<Integer>(); sig.add(nums[i]); sig.add(res); sig.add(nums[j]); fi.add(sig); System.out.println(sig.get(0)+"/"+sig.get(1)+"/"+sig.get(2)); // sig.clear(); break; } } } else if(res<0&&res>=nums[i]){ for(int key=i+1;nums[key]<0;key++){ if(nums[key]==res){ List<Integer> sig = new ArrayList<Integer>(); sig.add(nums[i]); sig.add(res); sig.add(nums[j]); fi.add(sig); System.out.println(sig.get(0)+"/"+sig.get(1)+"/"+sig.get(2)); // sig.clear(); break; } } } temp_j=nums[j]; j--; while(nums[j]>0&&nums[j]==temp_j) j--; } j=nums.length-1; temp_i=nums[i]; i++; while(nums[i]<0&&nums[i]==temp_i) i++; } if(nums[i]==0&&i+2<=nums.length-1) if(nums[i+1]==0&&nums[i+2]==0){ List<Integer> sig = new ArrayList<Integer>(); sig.add(0); sig.add(0); sig.add(0); fi.add(sig); System.out.println(sig.get(0)+"/"+sig.get(1)+"/"+sig.get(2)); } } return fi; }