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] 这个三元组。为了避免这种情况,要跳过这些相同的元素

相关推荐
Dlrb12114 小时前
C语言-指针三
c语言·算法·指针·const·命令行参数
Tisfy4 小时前
LeetCode 2540.最小公共值:双指针(O(m+n))
算法·leetcode·题解·双指针
IronMurphy4 小时前
【算法四十七】152. 乘积最大子数组
算法
淘矿人6 小时前
Claude辅助DevOps实践
java·大数据·运维·人工智能·算法·bug·devops
Cosolar6 小时前
万字详解:RAG 向量索引算法与向量数据库架构及实战
数据库·人工智能·算法·数据库架构·milvus
小江的记录本6 小时前
【Java基础】泛型:泛型擦除、通配符、上下界限定(附《思维导图》+《面试高频考点清单》)
java·数据结构·后端·mysql·spring·面试·职场和发展
ychqsq6 小时前
20.面试
经验分享·职场和发展
凯瑟琳.奥古斯特6 小时前
数据冗余与规范化的本质[数据库原理]
开发语言·数据库·职场和发展
落羽的落羽7 小时前
【算法札记】练习 | Week4
linux·服务器·数据结构·c++·人工智能·算法·动态规划