leetcode.windliang.cc/ 第一時間發佈java
無腦搜索,三層循環,遍歷全部的狀況。但須要注意的是,咱們須要把重複的狀況去除掉,就是 [1, -1 ,0] 和 [0, -1, 1] 是屬於同一種狀況的。算法
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++)
for (int k = j + 1; k < nums.length; k++) {
if (nums[i] + nums[j] + nums[k] == 0) {
List<Integer> temp = new ArrayList<Integer>();
temp.add(nums[i]);
temp.add(nums[j]);
temp.add(nums[k]);
//判斷結果中是否已經有 temp 。
if (isInList(res, temp)) {
continue;
}
res.add(temp);
}
}
}
return res;
}
public boolean isInList(List<List<Integer>> l, List<Integer> a) {
for (int i = 0; i < l.size(); i++) {
//判斷兩個 List 是否相同
if (isSame(l.get(i), a)) {
return true;
}
}
return false;
}
public boolean isSame(List<Integer> a, List<Integer> b) {
int count = 0;
Collections.sort(a);
Collections.sort(b);
//排序後判斷每一個元素是否對應相等
for (int i = 0; i < a.size(); i++) {
if (a.get(i) != b.get(i)) {
return false;
}
}
return true;
}
複製代碼
時間複雜度:n 表示 num 的個數,三個循環 O(n³),而 isInList 也須要 O(n),總共就是 $$O(n^4)$$,leetCode 複雜度到了 $$O(n^3)$$ 通常就報超時錯誤了,因此算法還得優化。數組
空間複雜度:最壞狀況,即 O(N), N 是指 n 個元素的排列組合個數,即 $$N=C^3_n$$,用來保存結果。優化
參考了這裏spa
主要思想是,遍歷數組,用 0 減去當前的數,做爲 sum ,而後再找兩個數使得和爲 sum。指針
這樣看來遍歷須要 O(n),再找兩個數須要 O(n²)的複雜度,仍是須要 O(n³)。code
巧妙之處在於怎麼找另外兩個數。cdn
最最優美的地方就是,首先將給定的 num 排序。blog
這樣咱們就能夠用兩個指針,一個指向頭,一個指向尾,去找這兩個數字,這樣的話,找另外兩個數時間複雜度就會從 O(n²),降到 O(n)。排序
而怎麼保證不加入重複的 list 呢?
要記得咱們的 nums 已經有序了,因此只須要找到一組以後,當前指針要移到和當前元素不一樣的地方。其次在遍歷數組的時候,若是和上個數字相同,也要繼續後移。文字表述比較困難,能夠先看下代碼。
public List<List<Integer>> threeSum(int[] num) {
Arrays.sort(num); //排序
List<List<Integer>> res = new LinkedList<>();
for (int i = 0; i < num.length-2; i++) {
//爲了保證不加入重複的 list,由於是有序的,因此若是和前一個元素相同,只須要繼續後移就能夠
if (i == 0 || (i > 0 && num[i] != num[i-1])) {
//兩個指針,而且頭指針從i + 1開始,防止加入重複的元素
int lo = i+1, hi = num.length-1, sum = 0 - num[i];
while (lo < hi) {
if (num[lo] + num[hi] == sum) {
res.add(Arrays.asList(num[i], num[lo], num[hi]));
//元素相同要後移,防止加入重複的 list
while (lo < hi && num[lo] == num[lo+1]) lo++;
while (lo < hi && num[hi] == num[hi-1]) hi--;
lo++; hi--;
} else if (num[lo] + num[hi] < sum) lo++;
else hi--;
}
}
}
return res;
}
複製代碼
時間複雜度:O(n²),n 指的是 num
空間複雜度:O(N),最壞狀況,即 N 是指 n 個元素的排列組合個數,即 $$N=C^3_n$$,用來保存結果。
對於遍歷,這裏用到了從兩頭同時遍歷,從而下降了時間複雜度,很妙!