leetcode hot100 15. 三数之和 medium

👉 题目禁止的是:

下标重复(同一个元素不能用两次)

结果三元组重复(值完全相同的三元组不能出现两次)

👉 题目并不禁止:

值相同但来自不同位置的元素

由三维降到二维, 针对任意索引i的nums[i] 求[i+1,size )范围内不重复的twoSum target = - nums[i];

  1. 排序数组,方便去重。
  2. 固定一个元素 nums[i],用双指针扫描剩余部分的数组来寻找另外两个数。

时间复杂度:O(n²)

排序是 O(n log n)。

双指针扫描是 O(n)。对于每个 i,双指针的扫描是 O(n) 的操作,而外层循环遍历了 n 个元素。

总的时间复杂度为 O(n²) +O(n log n) = O(max(n log n, n²)) = O(n²)

没有使用额外的存储结构(例如哈希表、栈等),而是仅使用了常数级的空间(如变量 i, left, right, res)。因此,空间复杂度是 O(1)

python 复制代码
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:

        if len(nums) < 3:
            return []

        nums.sort()   # 从小到大排序
        res =[]

        for i in range(len(nums)):
            if nums[i] >0:    # 已排序,第一个就>0,后面不会有匹配的, 退出当前循环
                break         # 不能 return [], 因为之前的循环res可能已经有值,只能break或return res 
            if i>0 and nums[i] == nums[i-1]:  # 当前nums[i]与nums[i-1]相同,前面已经处理过,跳过
                continue
            
            # 由三维降到二维,开始左右指针: 针对任意索引i的nums[i] 求[i+1,size )范围内不重复的twoSum target = - nums[i];
            # twoSum 开始
            left = i+1
            right = len(nums)-1
            while left < right:
                target = 0-nums[i]

                # 正好找到
                if nums[left] + nums[right]  == target:
                    res.append([nums[i], nums[left], nums[right]])
                    while(left < right and nums[left]==nums[left+1]):    # 跳过重复元素
                        left +=1
                    while(left < right and nums[right]==nums[right-1]):  # 跳过重复元素
                        right -= 1

                    # 正常移动双指针
                    left  += 1
                    right -= 1

                # 没找到
                elif nums[left] + nums[right] > target:  # 已排序,说明要再小一点
                    right -= 1  # 右指针左移 
                else:   #nums[left] + nums[right] < target:  # 已排序,说明要再大一点
                    left +=1 


        return res

在发现一个三元组时,为什么不是直接跳过首尾:left += 1;right -= 1,而是要判断

nums[left] == nums[left + 1]:

nums[right] == nums[right - 1]
避免重复三元组:因为数组是排过序的,可能会遇到值相同的元素。为了避免返回重复的三元组,需要跳过相同的元素。

假设数组已经排序:[-1, -1, 0, 1, 1]

我们找到的三元组是 [-1, 0, 1]。那么:

左指针 left 现在指向 0。

右指针 right 现在指向 1。

如果我们直接移动指针,左指针 left 会指向下一个 0,右指针 right 会指向下一个 1,这时候我们会重复添加 [-1, 0, 1] 这个三元组。为了避免这种情况,要跳过这些相同的元素

相关推荐
Σίσυφος19009 小时前
PCL法向量估计 之 RANSAC 平面估计法向量
算法·机器学习·平面
xhbaitxl9 小时前
算法学习day39-动态规划
学习·算法·动态规划
I_LPL10 小时前
day23 代码随想录算法训练营 回溯专题2
算法·hot100·回溯算法·求职面试
智者知已应修善业10 小时前
【洛谷P9975奶牛被病毒传染最少数量推导,导出多样例】2025-2-26
c语言·c++·经验分享·笔记·算法·推荐算法
m0_7369191010 小时前
C++中的委托构造函数
开发语言·c++·算法
小小小小王王王10 小时前
洛谷-P1886 【模板】单调队列 / 滑动窗口
c++·算法
网络安全-杰克10 小时前
Jmeter压力测试工具安装与使用
自动化测试·软件测试·测试工具·jmeter·职场和发展
PPPPPaPeR.10 小时前
光学算法实战:深度解析镜片厚度对前后表面折射/反射的影响(纯Python实现)
开发语言·python·数码相机·算法
看我干嘛!10 小时前
python第五次作业
算法
历程里程碑10 小时前
Linux 库
java·linux·运维·服务器·数据结构·c++·算法