# 15.3Sum <span class="tag" data-diff="medium" />
{%hackmd RN5D4nggQRO8wzNqxuvlNw %}
## 題目
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
**Example:**
```
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
```
## 思路
我覺得這題頗有<span class='tag' data-diff='hard'></span>的難度QQ雖然他看起來跟第一題一樣,但難度真的天差地遠,一開始我也打算用第一題的hash map解法,花 $O(n^2)$ 的時間紀錄`nums`中兩兩之和與0的差距,再loop過一遍把所有答案找出來。但這個做法有一個大問題,就是會重複,因為`nums`中的數字是可以重複的,由於沒有記錄每個數字在`nums`中出現過幾次,就會不知道可不可以放在tuple中。 加入許多限制條件後,時間花費跟直接用3層迴圈一樣,而且都會TLE,最後沒有辦法只好從Disscussion中找解答。
```javascript
var threeSum = function(nums) {
const results = []
if (nums.length < 3) return results
nums = nums.sort((a, b) => a - b)
let target = 0
for (let i = 0; i < nums.length - 2; i++) {
if (nums[i] > target) break
if (i > 0 && nums[i] === nums[i - 1]) continue
let j = i + 1
let k = nums.length - 1
while (j < k) {
let sum = nums[i] + nums[j] + nums[k]
if (sum === target) {
results.push([nums[i], nums[j], nums[k]])
while (nums[j] === nums[j + 1]) j++
while (nums[k] === nums[k - 1]) k--
j++
k--
} else if (sum < target) {
j++
} else {
k--
}
}
}
return results
};
```
一開始如果`nums`沒有到3個element,就直接回傳空array,接著loop過每一個element,去找出該element所需的另外兩個數字。
由於一開始已經sort過,所以當current element大於目標(`0`)的時候,後面在怎麼找,相加都不會等於目標,就可以跳出loop了。
要找出剩下兩個數字,會從sorted array的兩端開始找(`j`、`k`),如果三者相加剛好等於目標(`0`),就push進result中,如果比0還小,就讓佐指標前進去找更大的數;若比0還大,讓右指標往左找較小的數。過程中為了加速,可以跳過連續的相同數字,當左右指標相遇後,則搜尋完成,進到下一個iteration去找result。