在陣列中找出四個數字的和等於指定數字(4Sum)
阿新 • • 發佈:2019-01-04
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note: The solution set must not contain duplicate quadruplets.
For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0. A solution set is: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
說到遍歷,第一反應就是先把原陣列的四個數字的組個都拿出來,然後再看那個符合要求,但是這樣的做法估計在時間複雜度這關就過不了,就算出所有的組合就已經很費時間了。所以得另想辦法……
如果是三個數字的話,貌似簡單了許多,還有一點就是題目中沒有說我們不可以改變原始陣列,所以我們可以對這個陣列稍稍排個序,這又大大簡化了我們的問題,因為排序以後加和調整的方向是確定的,直接看程式碼吧,這樣容易理解一些。
三個數字:
public class ThreeSum { /** * @param nums * @return */ public List<List<Integer>> threeSum(int[] nums) { List<List<Integer>> list = new ArrayList<>(); List<Integer> numsList = new ArrayList<>(); for (int i = 0; i < nums.length; i++) numsList.add(nums[i]); Collections.sort(numsList); int len = numsList.size(); for (int i = 0; i < len - 2; i++){ if (i > 0 && numsList.get(i - 1).equals(numsList.get(i))) continue; Integer a = numsList.get(i); int low = i + 1; int high = len - 1; while (low < high){ Integer b = numsList.get(low); Integer c = numsList.get(high); if ((a + b + c) == 0){ List<Integer> tl = new ArrayList<>(); tl.add(a); tl.add(b); tl.add(c); list.add(tl); while (low < len - 1 && numsList.get(low).equals(numsList.get(low + 1))) low++; while (high > 0 && numsList.get(high).equals(numsList.get(high - 1))) high--; low++; high--; }else if ((a + b + c) > 0){ while (high > 0 && numsList.get(high).equals(numsList.get(high - 1))) high--; high--; }else{ while (low < len - 1 && numsList.get(low).equals(numsList.get(low + 1))) low++; low++; } } } return list; } }
上面的實現還是比較好理解的,首先呢對陣列進行排序,排序的目的顯而易見,就是為了方便調整,三個數字分別為a,b,c。a就是從陣列開頭開始遍歷,b,c一個放在a的下一個位置,一個放在陣列的最後一個位置,如果當前三個傢伙的值跟target相等,那就啥也不說了了,直接新增,如果大於或者小於,那就得調整啦,具體咋調整程式碼寫的很清楚,這裡就不羅嗦啦……
那麼現在回頭再看這個問題,會發現無非就是在三個的基礎上再加一個數字變成四個,那行,還是上面的思路,無非就是兩層迴圈麼,程式碼相似度很大,於是有了下面的實現:
程式碼如下:
實話講,這個程式碼的時間複雜度還是有些高,如果字串變態些還是怕扛不住……後面有好辦法再跟新吧public class FourSum { public List<List<Integer>> fourSum(int[] nums, int target) { List<List<Integer>> result = new ArrayList<>(); List<Integer> integerList = new ArrayList<>(); for (int num : nums) { integerList.add(num); } Collections.sort(integerList); int len = integerList.size(); for (int i = 0; i < len - 3; i++) { if (i > 0 && integerList.get(i).equals(integerList.get(i - 1))) continue; Integer a = integerList.get(i); Integer rest = (Integer) target - a; for (int j = i + 1; j < len - 2; j++) { if (j > i + 1 && integerList.get(j - 1).equals(integerList.get(j))) continue; Integer b = integerList.get(j); int low = j + 1; int high = len - 1; while (low < high) { Integer c = integerList.get(low); Integer d = integerList.get(high); if (rest - (b + c + d) == 0) { List<Integer> tl = new ArrayList<>(); tl.add(a); tl.add(b); tl.add(c); tl.add(d); result.add(tl); while (low < len - 1 && integerList.get(low).equals(integerList.get(low + 1))) low++; while (high > j + 1 && integerList.get(high).equals(integerList.get(high - 1))) high--; low++; high--; } else if (rest - (b + c + d) > 0) { while (low < len - 1 && integerList.get(low).equals(integerList.get(low + 1))) low++; low++; } else { while (high > j + 1 && integerList.get(high).equals(integerList.get(high - 1))) high--; high--; } } } } return result; } }