题目要求:
Design an algorithm for the 3-SUM problem that takes time proportional to n2 in the worst case. You may assume that you can sort the n integers in time proportional to n2 or better.
分析:
《算法4》这本书提供的TwoSumFast解法为NlogN,ThreeSumFast解法为N2logN,根据课后练习,要实现3Sum复杂度为N2,建议先把2Sum复杂度实现为N。同时教材提示用排好序的数组可以实现复杂度N。我想了很久,没有发现排好序的数组对复杂度降至N有太大帮助,于是在网上搜索了下大家的做法。网上的大部分都是建议用set或map来做,我决定采用map试试,果然用map很方便。代码如下:
1 import java.util.Arrays; 2 import java.util.HashMap; 3 4 public class TwoSumLinear { 5 public static int count(int[] a){ 6 int cnt = 0; 7 int n = a.length; 8 HashMap<Integer,Integer> map = new HashMap<Integer,Integer>(); 9 for(int i =0; i<n;i++){ 10 if(map.get(a[i]) == null) map.put(a[i], i); 11 Integer negIndex = map.get(-a[i]); 12 if(negIndex != null && negIndex != i){ 13 System.out.println("a["+negIndex+"]="+(-a[i])+"和a["+i+"]="+a[i]); 14 cnt++; 15 } 16 } 17 return cnt; 18 } 19 public static void main(String[] args){ 20 int[] a = { 30, -40, -20, -10, 40, 0, 10, 5 }; 21 System.out.println(Arrays.toString(a)); 22 System.out.println(count(a)); 23 } 24 }
3Sum的作业提示可以先将数组排序,基于这个思路,结合写过的2Sum线性实现方法,写出了复杂度为N2的3Sum,个人认为实现的方式已经很精简了。
1 import java.util.Arrays; 2 import java.util.HashMap; 3 4 public class ThreeSumQuadratic { 5 public static int count(int[] a, int target) { 6 Arrays.sort(a);// 数组从小到大排序,后面要使用有序数组的性质简化运算 7 System.out.println(Arrays.toString(a)); 8 System.out.println("target="+target); 9 int cnt = 0; 10 int n = a.length; 11 HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); 12 for (int i = 0; i < n; i++) { 13 map.put(a[i], i); //以数组value为key,index为map值 14 } 15 for (int i = 0; i < n - 1; i++) {//i不会超过n-2 16 for (int j = i + 1; j < n; j++) {//j从i+1开始统计,不会超过n-1 17 int smallValue = a[i] + a[j]; //因为排好序了,所以最开始的a[i]+a[j] 18 if (smallValue > target) //当a[i]+a[j]>target时没必要计算了,因为后续的查找就会重复 19 break; 20 int bigValue = target-smallValue; //计算出对应的数值较大的value 21 Integer bigIndex = map.get(bigValue); //查找数值较大的value所在的位置 22 if (bigIndex != null && bigIndex > i && bigIndex > j) { 23 System.out.println( 24 "[" + i + "]=" + a[i] + ",[" + j + "]" + a[j] + ",[" + bigIndex + "]" + (bigValue)); 25 cnt++; 26 } 27 } 28 } 29 return cnt; 30 } 31 32 public static void main(String[] args) { 33 int[] a = { 30, -40, -20, -10, 40, 0, 10, 5 }; 34 System.out.println(count(a,0)); 35 } 36 }