# 15. 3Sum ## 題目概要 從陣列中找到三個數,三個數相加等於 0,結果可能有很多個,且同樣三個數無論怎麼排序都算同個結果。 ## 解題技巧 1. 首先需要給陣列排序 2. 遍歷陣列從 0 ~ length - 2 (邊界) 3. 如果當前的數字等於前一個數字則跳過這個數(去重) 4. 如果數字不同,則設置 start = i + 1 ; end = length - 1;計算 i, start, end 三個數的和比零大還是小,如果比 0 小 `start++`,如果比 0 大 `end--`,如果等於 0 就把這三個數放進結果裡 5. 返回結果 ## 解題流程 1. 舉個例子,假設現在有一陣列為`[-1, 0, 1, 2, -1, -4]`,每一步驟說明如下: ![](https://i.imgur.com/NeWNw0u.png) 2. 因為剛剛三數相加小於 0 所以 start 往後移一位到 -1,再次相加結果還是相同,所以 `start++` ![](https://i.imgur.com/sqHWTxN.png) 3. -4 + 0 + 2 還是小於 0,繼續 `start++` ![](https://i.imgur.com/3feZI8d.png) 4. 最後 -4 + 1 + 2 還是小於 0,但循環已經結束,所以我們將 `i + 1`: ![](https://i.imgur.com/rHhkrMQ.png) 5. 下一輪開始,`start = i + 1`,end 依然是 `length - 1` ![](https://i.imgur.com/8l18LxM.png) 6. (-1)+0+2 比 0 大,所以 `end--`: ![](https://i.imgur.com/E0OnYUb.png) 7. -1+0+1=0,所以把 `[-1, 0, 1]` 存入結果 ![](https://i.imgur.com/2HSLsti.png) 步驟依此類推直到全部數字遍歷完畢。 ## 程式碼 ```javascript= /** * @param {number[]} nums * @return {number[][]} */ var threeSum = function(nums) { let result = []; nums.sort((a, b) => a - b); // 首先排序 for(let i = 0; i < nums.length - 2; i++) { if (i === 0 || nums[i] !== nums[i - 1]) { let start = i + 1, end = nums.length - 1; while(start < end) { if (nums[i] + nums[start] + nums[end] === 0) { result.push([nums[i], nums[start], nums[end]]); start++; end--; // 去重 while(start < end && nums[start] === nums[start - 1]) { start++; } while(start < end && nums[end] === nums[end + 1]) { end--; } } else if (nums[i] + nums[start] + nums[end] < 0) { start++; } else { // > 0 end--; } } } } return result; }; ``` ![](https://i.imgur.com/941mJwj.png)