【Leetcode】三数之和

1 题目

给你一个整数数组 nums ,判断是否存在三元组 nums\[i, numsj, numsk] 满足 i != j、i != k 且 j != k ,同时还满足 numsi + numsj + numsk == 0 。请你返回所有和为 0 且不重复的三元组。

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

示例 1:

输入:nums = -1,0,1,2,-1,-4

输出:\[-1,-1,2,-1,0,1]

解释:

nums0 + nums1 + nums2 = (-1) + 0 + 1 = 0 。

nums1 + nums2 + nums4 = 0 + 1 + (-1) = 0 。

nums0 + nums3 + nums4 = (-1) + 2 + (-1) = 0 。

不同的三元组是 -1,0,1-1,-1,2

注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:nums = 0,1,1

输出:\[\]

解释:唯一可能的三元组和不为 0 。

示例 3:

输入:nums = 0,0,0

输出:\[0,0,0]

解释:唯一可能的三元组和为 0 。

2 分析

这道题乍一看最直观的解法是三重遍历,但时间复杂度是O(N^3),而且无法解决重复的问题。因此,进阶解法需要解决以下两个问题:

  • 时间复杂度
  • 重复元素

通过对数组排序,可以将相同的元素放到一起,且单调数组更容易做推断。接下来,只需要固定元素numsi,寻找j和k使得numsj+numsk=-numsi即可。让left和right指针分别指向数组左边的小元素和右边的大元素,基于单调性,如果numsleft+numsright<-numsi,只需要将left右移,就可以得到更大的和;如果如果numsleft+numsright>-numsi,只需要将right左移,就可以得到更小的和。这样只需要两层遍历。

另一个问题是怎么解决重复元素?只需要当前位置与前一个位置比较,如果相同则跳过。这里分三种情况,

  • 第一种情况是固定位置numsi,只需要比较每个循环中numsi与前一个位置numsi-1是否相等,如果相等则不需要再做循环,直接continue即可。
  • 第二种情况是left指针位置,当找到满足要求的三元组后,left指针会加一,right指针会减一,因此需要比较numsleft与前一个位置numsleft-1是否相等,如果相等则继续对left加一,直到left不比right小;
  • 第三种情况是right指针位置,也是在找到满足要求的三元组之后,需要比较numsright与后一个位置numsright+1是否相等,如果相等则继续对right减一,直到right不比left大。

从时间复杂度上看,排序复杂度O(n log n) ,后续双层遍历复杂度O(n²)。根据大O表示法,O(n log n + n²) = O(n²)。因此时间复杂度为O(n²)。

3 代码

python 复制代码
def threeSum(self, nums):
    """
    :type nums: List[int]
    :rtype: List[List[int]]
    """
    nums.sort()
    n = len(nums)
    res = []
    for i in range(n-1):
        if i>0 and nums[i]==nums[i-1]:
            continue
        target = -nums[i]
        left, right = i+1, n-1
        while left < right:
            cur_sum = nums[left] + nums[right]
            if  cur_sum == target:
                res.append([nums[i], nums[left], nums[right]])
                left += 1
                right -= 1
                while left<right and nums[left] == nums[left-1]:
                    left +=1
                while left<right and nums[right]== nums[right+1]:
                    right -= 1
            elif cur_sum > target:
                right -= 1  
            else:
                left += 1
    return res
相关推荐
地平线开发者2 小时前
【模型轻量化专题】衡量模型轻量性的指标
算法
学习星球5 小时前
OFDM技术精讲:正交性推导、循环前缀原理与80行Python链路仿真(附实测数据)
算法·面试·前端框架
alphaTao11 小时前
LeetCode 每日一题 2026/8/24-2026/8/30
python·算法·leetcode
Interview Aid11212 小时前
TikTok OA 四题分享|半小时内 AC,题目基本都是实现题
java·开发语言·算法·面试·职场和发展
顶点多余21 小时前
那些在算法中适合巩固的知识点---1
java·前端·算法
AI情绪识别开源1 天前
检信 ALLEMOTION OS 加密打包可执行程序 — 全面测试报告版本: v1.3功能测试 / 性能测试 /
开发语言·数据结构·人工智能·功能测试
罗西的思考1 天前
【Agentic RL / 强化学习框架】Molt 设计解读
人工智能·算法·机器学习
hahaha60161 天前
HLS高层次综合设计技巧--C++类和模板
图像处理·人工智能·算法·计算机视觉
多弗朗皮卡丘1 天前
算法详解4:买卖股票的最佳时机系列(上)
算法
维克兜率天1 天前
【维克】动量指标家族:RSI、ROC、CCI、Momentum全面解析
python·算法