【LeetCode】3Sum 解題報告
阿新 • • 發佈:2018-12-27
這道題憑我現有知識實在解答不上來,只好網上搜索解法,才發現 K Sum 是一類問題,但是網上沒有比較簡潔的程式碼,我想對於初學者來說,可能還是想先看看這道題怎麼解,然後才有興趣去看其擴充套件吧。
【題目】
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
- 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)【解析】
K Sum問題是一個系列,部落格 http://tech-wonderland.net/blog/summary-of-ksum-problems.html 總結得比較完整,有興趣可以去看。
作為初學者,我們用最簡潔的思路來說一下這道題怎麼解。
暴力解決法是每個人都能想到的,三層for迴圈,時間複雜度是O(n^3),而且還要處理重複的問題,顯然不是題目想要的解法。
那能不能降到O(n^2)?排序演算法的時間複雜度為O(nlgn),小於O(n^2),那麼我們不妨先對陣列排個序。
排序之後,我們就可以對陣列用兩個指標分別從前後兩端向中間掃描了,如果是 2Sum,我們找到兩個指標之和為target就OK了,那 3Sum 類似,我們可以先固定一個數,然後找另外兩個數之和為第一個數的相反數就可以了。
程式碼不難,先看了再說。
【Java程式碼】O(n^2)
public class Solution { List<List<Integer>> ret = new ArrayList<List<Integer>>(); public List<List<Integer>> threeSum(int[] num) { if (num == null || num.length < 3) return ret; Arrays.sort(num); int len = num.length; for (int i = 0; i < len-2; i++) { if (i > 0 && num[i] == num[i-1]) continue; find(num, i+1, len-1, num[i]); //尋找兩個數與num[i]的和為0 } return ret; } public void find(int[] num, int begin, int end, int target) { int l = begin, r = end; while (l < r) { if (num[l] + num[r] + target == 0) { List<Integer> ans = new ArrayList<Integer>(); ans.add(target); ans.add(num[l]); ans.add(num[r]); ret.add(ans); //放入結果集中 while (l < r && num[l] == num[l+1]) l++; while (l < r && num[r] == num[r-1]) r--; l++; r--; } else if (num[l] + num[r] + target < 0) { l++; } else { r--; } } } }
注意,對於 num[i],尋找另外兩個數時,只要從 i+1 開始找就可以了。
這種寫法,可以避免結果集中有重複,因為陣列時排好序的,所以當一個數被放到結果集中的時候,其後面和它相等的直接被跳過。