力扣——15三数之和

目录

1.题目描述:

2.算法思路:

3.代码展示:


1.题目描述:

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

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

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-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.算法思路:

算法思路(双指针法)​

​1. 排序预处理​

  • ​目的​​:使数组有序,便于使用双指针技巧和去重。
  • ​操作​​:调用 sort(nums.begin(), nums.end()),时间复杂度 ​​O(n log n)​​。

​2. 外层循环(固定第一个数 first)​

  • ​遍历范围​​:first 从 0 到 nums.size() - 1
  • ​去重​​:
    • 如果 nums[first] == nums[first - 1],跳过当前 first,避免重复解。
  • ​计算目标值​​:
    • target = -nums[first],表示剩余两数之和需要等于 target

​3. 内层双指针(second 和 third)​

  • ​初始化​​:
    • second = first + 1(左指针)。
    • third = nums.size() - 1(右指针)。
  • ​移动规则​​:
    • 如果 nums[second] + nums[third] > target,则 third--(右指针左移,减少和)。
    • 如果 nums[second] + nums[third] < target,则 second++(左指针右移,增加和)。
    • 如果 nums[second] + nums[third] == target,记录解,并跳过重复的 second 和 third
  • ​终止条件​​:
    • 当 second >= third 时,退出循环。

​4. 去重优化​

  • ​外层去重​​:跳过重复的 nums[first]
  • ​内层去重​​:在找到解后,跳过重复的 nums[second] 和 nums[third]

​时间复杂度分析​

  1. ​排序​​:O(n log n)
  2. ​外层循环​​:O(n)
    • 每个 first 只遍历一次。
  3. ​内层双指针​​:O(n)
    • 对于每个 firstsecond 和 third 总共最多遍历 n 次(second 从左到右,third 从右到左,不会重复扫描)。
  4. ​总时间复杂度​​:
    • ​O(n log n) + O(n²) = O(n²)​​(当 n 较大时,O(n²) 主导)。

3.代码展示:

vector<vector<int>> threeSum(vector<int>& nums) {
    vector < vector<int>>result;
    //先进行排序,方便后续的去重操作
    sort(nums.begin(), nums.end());
    for (int first = 0; first < nums.size(); first++) {
        //跳出重复的first
        if (first > 0 && nums[first] == nums[first - 1]) {
            continue;
        }
        
        
        int third = nums.size() - 1;//始终指向最后一个元素
        int target = -nums[first];//用于判断,相当与second+third和target的关系
       
        for (int second = first + 1; second < nums.size(); second++) {
            //跳出重复的second
            if (second > first+1 && nums[second] == nums[second - 1]) {
                continue;
            }
            //接下来,判断三者的关系,second+third > target,则third--,直到second>third
            while (second < third && nums[second] + nums[third] > target) {
                //指针后移
                third--;
            }
            //如果相等就插入
            if (second == third) {
                break;
            }
            if (nums[second] + nums[third] == target) {
                result.push_back({ nums[first] ,nums[second] ,nums[third] });
            }  
        }
    }

    return result;
}

15. 三数之和 - 力扣(LeetCode)https://leetcode.cn/problems/3sum/description/

### LeetCode 三数之和问题的 Python 解法 对于给定的一个包含 n 个整数的数组 nums,判断是否存在三个元素 a, b, c ,使得 a + b + c = 0?找出所有满足条件且不重复的三元组。 #### 方法一:暴力求解 (超时) 最直观的方法是对每个可能的组合进行遍历并检查其总和是否等于零。然而这种方法的时间复杂度为 O(n³),当数据量较大时会超出时间限制[^2]。 ```python def threeSum(nums): result = [] length = len(nums) for i in range(length-2): for j in range(i+1,length-1): for k in range(j+1,length): if nums[i]+nums[j]+nums[k]==0: temp=[nums[i],nums[j],nums[k]] temp.sort() if temp not in result: result.append(temp) return result ``` 此方法虽然可以解决问题但是效率低下,在实际应用中并不推荐使用。 #### 方法二:哈希表优化 为了提高性能,可以在两层循环的基础上利用哈希集合来存储已经访问过的数值及其索引位置,从而快速定位第三个数的位置。这样做的好处是可以减少一层显式的嵌套循环,降低算法的整体开销至O(n²)[^5]。 ```python from collections import defaultdict class Solution(object): def threeSum(self, nums): """ :type nums: List[int] :rtype: List[List[int]] """ res = set() seen = {} for index_i,i in enumerate(nums[:-2]): if i not in seen: seen[i]=index_i for j in nums[index_i+1:]: target=-i-j if target in seen and seen[target]!=index_i : triplet=tuple(sorted([i,j,target])) if triplet not in res: res.add(triplet) return list(map(list,res)) ``` 上述实现通过 `set` 来去重,并且借助字典记录已处理过的目标值,有效防止了重复项的加入。 #### 方法三:双指针技巧 先对输入列表进行排序操作,之后固定第一个数字作为当前考虑的一部分;接着采用两个游标的策略——左端指向下一个待考察元素而右端则位于序列末端。根据这三个选定元素计算得到的结果调整两端游标直至找到符合条件或者无法继续为止。该方案同样具有较好的时空表现特性,适用于大多数情况下的需求[^1]。 ```python class Solution(object): def threeSum(self, nums): """ :type nums: List[int] :rtype: List[List[int]] """ nums.sort() N=len(nums) ans=[] for t in range(N-2): if t>0 and nums[t]==nums[t-1]: continue l,r=t+1,N-1 while l<r: total=nums[t]+nums[l]+nums[r] if total==0: ans.append((nums[t],nums[l],nums[r])) while l<N-1 and nums[l]==nums[l+1]:l+=1 while r>0 and nums[r]==nums[r-1]:r-=1 l+=1;r-=1 elif total<0:l+=1 else:r-=1 return ans ``` 这段代码实现了基于双指针技术的有效解决方案,能够高效地解决三数之和的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值