---
# System prepended metadata

title: 15. 3Sum
tags: [pointer, Leetcode, medium, python, Top 100 Liked Questions]

---

###### tags: `Leetcode` `medium` `pointer` `python` `Top 100 Liked Questions`

# 15. 3Sum

## [題目連結:] https://leetcode.com/problems/3sum/

## 題目:
Given an integer array nums, return all the triplets ```[nums[i], nums[j], nums[k]]``` such that ```i != j, i != k,``` and ```j != k```, and ```nums[i] + nums[j] + nums[k] == 0```.

Notice that the solution set must not contain duplicate triplets.

**Example 1:**
```
Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]
Explanation: 
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0.
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0.
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0.
The distinct triplets are [-1,0,1] and [-1,-1,2].
Notice that the order of the output and the order of the triplets does not matter.
```
Example 2:
```
Input: nums = [0,1,1]
Output: []
Explanation: The only possible triplet does not sum up to 0.
```
Example 3:
```
Input: nums = [0,0,0]
Output: [[0,0,0]]
Explanation: The only possible triplet sums up to 0.
```

## 解題想法:
兄弟題目: [16. 3Sum Closest](/-2KGuo22S3qNrqbNTpvC_w)、[18. 4Sum](/DxMPstejSjGGRPi7EHckdA)
* 題目要求: 給一數組，要求三數和=0，且每種組合不能重複
    * use two pointer
    * for 迴圈固定一值(i)
    * 找two pointer(j、k)與i之nums[i]+nums[j]+nums[k]=0
        * j=i+1
        * k=len(nums)
    * 因為避免找重複的組合，所以**數組一定要先排序**!!
    * 優化:因為是排序好再找，因此nums[i]一定是最小值，若nums[i]>0，則一定沒解了，因為nums[j]、nums[k]一定更大，可直接break

## python:
time:O(nlongn+n^2) space:O(1)
``` python=
class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        #use two pointer
        res =[]
        #一定要先排序
        nums.sort()
        for i in range(len(nums)-2):
            #和為0 sort完 jk在i後面 若i都>0了 肯定沒搞頭了
            if nums[i]>0:
                break
            #若遇重複i，只能使用第一次出現的  所以跳過此輪
            #因為確保i=0與i=1時nums[i]相同值時 要優先用i=0 所以要規定判別於i>0
            if i>0 and nums[i]==nums[i-1]:
                continue
            j = i+1
            k = len(nums)-1
            while j<k:
                #nums之i+j+k值為0 fuck ya
                if nums[i]+nums[j]+nums[k]==0:
                    res.append([nums[i],nums[j],nums[k]])
                    j+=1
                    k-=1
                    #跳過重複的nums[j]
                    while j<k and nums[j]==nums[j-1]:
                        j+=1
                    #跳過重複的nums[k]
                    while j<k and nums[k]==nums[k+1]:
                        k-=1
                #總值過小 增加j
                elif nums[i]+nums[j]+nums[k]<0:
                    j+=1
                #總值過大 減k
                else:
                    k-=1
        return res

if __name__ == '__main__':
    result = Solution()
    nums = [-1,0,1,2,-1,-4]
    ans = result.threeSum(nums)
    print(ans)
```