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

相关推荐
机器学习之心11 小时前
LSBoost增强算法回归预测+SHAP可解释分析+新数据预测(多输入单输出)MATLAB代码
算法·matlab·回归·lsboost·shap可解释分析
重庆小透明12 小时前
【面试问题】java字节八股部分
java·面试·职场和发展
AI-Ming12 小时前
注意力机制
算法·ai·ai编程
ℳ๓₯㎕.空城旧梦12 小时前
C++中的解释器模式
开发语言·c++·算法
x_xbx12 小时前
LeetCode:2. 两数相加
算法·leetcode·职场和发展
兔子77312 小时前
RNN 终于讲明白了:从“模型为什么需要记忆”到 Elman 1990 全文吃透
算法
兔子77312 小时前
LSTM 终于讲明白了:从“RNN 为什么会忘”到 Hochreiter & Schmidhuber 1997 全文吃透
算法
ECT-OS-JiuHuaShan12 小时前
朱梁万有递归元定理,重构《阴符经》
算法·重构
_日拱一卒13 小时前
LeetCode:最长连续序列
算法·leetcode·职场和发展
2401_8795034113 小时前
C++与FPGA协同设计
开发语言·c++·算法