本题出自力扣,难度:中等

题目:

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

 

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:

输入:nums = []
输出:[]
示例 3:

输入:nums = [0]
输出:[]
 

提示:

0 <= nums.length <= 3000
-105 <= nums[i] <= 105

 

 

需要注意,当数据量过大时超时的问题,参考大神们的解法,自己理解了一下,详细看注释

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        a = []
        # 先排序
        nums.sort()
        # nums元素小于3,则不成立,直接返回[]
        if len(nums) < 3:
            return []
        # 排序后,第一个元素大于0或者最后一个元素小于0,则肯定不成立,返回[]
        if nums[0] > 0 or nums[-1] < 0:
            return []

        # 循环列表,最后两位元素就不用循环了(因为需要3个数相加)
        # 现在假设,v是第一位数字,t是第二位数字的下标,j是第三位数字的下标
        for k,v in enumerate(nums[:-2]):
            # 如果元素大于0后,就跳出循环,因为后面的数大于0
            if v > 0:
                break
            # 如果 k不等于0 而且 前一个元素等于现在的元素,就跳出此次循环
            if k != 0 and nums[k-1] == v:
                continue

            # t是左边开始移动的数字(初始值为最左边第二位)
            # j是右边开始移动的数字(初始值为最右边第一位)
            t = k  + 1
            j = len(nums) - 1
            # 当左边开始移动的数字小于右边开始移动的数字下标时循环
            while t < j:
                # 计算三位数字之和
                s = v + nums[t] + nums[j]
                # 如果三位数之和小于0,因为第一位数字在这个循环是固定的,就要找更大的数字,即最二位数字向右移(列表由小到大排序)
                if s < 0:
                    t += 1
                    # 如果右移时,出现相同的数字,就要跳过(不用重复计算),且下标加一
                    while t < j and nums[t] == nums[t-1]:
                        t += 1
                # 如果三位数之和大于0,因为第一位数字在这个循环是固定的,就要找更小的数字,即第三位数字向左移(列表由小到大排序)
                elif s > 0:
                    j -= 1
                    # 如果左移时,出现相同的数字,就要跳过(不用重复计算),且下标加一
                    while t < j and nums[j] == nums[j+1]:
                        j -= 1
                # 如果等于0,则加入a列表,因为单纯向右移动第二位(变大)或左移第三位(变小),三个数之和都会只会单纯的变大或变小,所以第二位向右移第三位向左移,同样,出现重复数字,则跳过且下标加一或减一
                else:
                    a.append([v,nums[t],nums[j]])
                    t += 1
                    j -= 1
                    while t < j and nums[t] == nums[t-1]:
                        t += 1
                    while t < j and nums[j] == nums[j+1]:
                        j -= 1             
        return a