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:
For example, given array S = {-1 0 1 2 -1 -4}, A solution set is: (-1, 0, 1) (-1, -1, 2)
思路:假如直接采用三重遍历暴力破解,时间复杂度为O(n^3)。可以参考两个数求和的办法,对于有序数组,找出两个数的和是N的时间复杂度是O(n)。对数组排序,时间复杂度是O(nLog(n))。最后问题变成先选取一个数,然后再剩下的数组中查询target-nums[i]的两个数,注意查重的办法,那么总的时间复杂度O(n^2)+O(nlog(n))=O(n^2)。
public class Solution { public List<List<Integer>> threeSum(int[] nums) { Arrays.sort(nums); int len=nums.length; List<List<Integer>> list=new ArrayList<>(); for(int i=0;i<len-2;i++) { //去重 if(i>0 && nums[i]==nums[i-1]) continue; int target2=0-nums[i]; twoSum(nums, i+1, target2, list); } return list; } public void twoSum(int [] nums,int start,int target,List<List<Integer>> list) { int head=start, end=nums.length-1; while(head<end) { int sum=nums[head]+nums[end]; if(sum<target) { head++; } else if(sum>target) { end--; } else { List<Integer> temp=new ArrayList<>(); temp.add(nums[start-1]); temp.add(nums[head]); temp.add(nums[end]); list.add(temp); //排除可能出现的重复情况,由于是有序数组,从小到大,所以只要一个一个的找重复并跳过即可 int k=head+1; while(k<end && nums[k]==nums[head])k++; head=k; k=end-1; while(k>head && nums[k]==nums[end])k--; end=k; } } } }
Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
For example, given array S = {-1 2 1 -4}, and target = 1. The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
public class Solution { public int threeSumClosest(int[] nums, int target) { Arrays.sort(nums); int dis=Integer.MAX_VALUE; int result=0; for(int i=0;i<nums.length-2;i++) { int target2=target-nums[i]; int re=twoSumCloest(nums, i+1, target2); int d=Math.abs(target-re-nums[i]); if(d<dis) { dis=d; result=re+nums[i]; if(d==0) return target; } } return result; } public int twoSumCloest(int [] nums,int start,int target) { int head=start,tail=nums.length-1; int re=0,d=Integer.MAX_VALUE; while(head<tail) { int sum=nums[head]+nums[tail]; if(sum<target) { int dis=target-sum; if(dis<d) { d=dis; re=sum; } head++; } else if(target<sum) { int dis=sum-target; if(dis<d) { d=dis; re=sum; } tail--; } else { return target; } } return re; } }