LeetCode15.三数之和

这篇具有很好参考价值的文章主要介绍了LeetCode15.三数之和。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

15.三数之和

一、题目

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != 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 。

提示:

  • 3 <= nums.length <= 3000
  • -105 <= nums[i] <= 105
二、解法
方法一:哈希法(非常烧脑的办法,我自己一开始没想出来)

直接给出代码,我感觉最难想的就是注释部分,有兴趣的话可以用{-2,-2,-2,-1,-1,-1,0,0,0,1,1,1,2,2,2}这个案例自己推一推,就能理解代码里为什么这么做了。

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> result;
        sort(nums.begin(),nums.end());
        for(int i = 0; i < nums.size(); i++){
            if (nums[i] > 0) {
                break;
            }
            //当元素a前一个元素已经被处理过的时候,就跳过
            if(i > 0 && nums[i] == nums[i-1]){
                continue;
            }
            unordered_set<int> s;   
            for(int j = i + 1; j < nums.size(); j++){
                //当元素b和前两位相等,且前两位都不是a的情况下,可以跳过
                if(j>i+2 && nums[j-1]==nums[j] && nums[j-2]==nums[j-1]){
                    continue;
                }
                int c = 0-nums[i]-nums[j];
                if(s.find(c) != s.end()){
                    result.push_back({nums[i],nums[j],c});
                    s.erase(c); //如果减出来的元素曾经存在于s中,就消除s里所有等于c的元素
                }else{
                    s.insert(nums[j]);
                }
            }
        }
        return result;
    }
};
方法二:双指针(推荐)

算法思路:

给定一个整数数组 nums,我们需要找到所有满足以下条件的三元组 [nums[i], nums[j], nums[k]]

  1. i != ji != kj != k
  2. nums[i] + nums[j] + nums[k] == 0

我们可以使用双指针的方法。

首先,对数组进行排序,这样可以方便后续的指针移动操作。然后,我们遍历排序后的数组,将当前元素作为三元组的第一个元素。使用两个指针,一个指向当前元素的下一个位置,另一个指向数组的最后一个位置。

在指针移动的过程中,我们计算当前三个元素的和 sum = nums[i] + nums[left] + nums[right]

  • 如果 sum 等于零,说明找到了一个满足条件的三元组,将这个三元组添加到结果列表中。
  • 如果 sum 小于零,说明当前和偏小,我们需要增加和的值,因此将左指针向右移动一位。
  • 如果 sum 大于零,说明当前和偏大,我们需要减小和的值,因此将右指针向左移动一位。

内部去重操作:在移动指针时,我们需要跳过重复的元素,以避免生成重复的三元组。如果当前指针所指的元素与前一个元素相同,我们可以继续移动指针,直到找到一个不同的元素为止。

详细实现:

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(), nums.end());  // 对数组进行排序
        vector<vector<int>> result;  // 存储结果的二维数组

        for (int i = 0; i < nums.size() - 2; ++i) {
            if (i > 0 && nums[i] == nums[i - 1])
                continue;  // 外层循环去重操作

            int left = i + 1;  // 左指针
            int right = nums.size() - 1;  // 右指针

            while (left < right) {
                int sum = nums[i] + nums[left] + nums[right];

                if (sum == 0) {  // 找到满足条件的三元组
                    result.push_back({nums[i], nums[left], nums[right]});

                    // 内部循环去重操作
                    while (left < right && nums[left] == nums[left + 1])
                        left++;
                    while (left < right && nums[right] == nums[right - 1])
                        right--;

                    left++;  // 移动指针
                    right--;
                } else if (sum < 0) {
                    left++;  // 增加和的值
                } else {
                    right--;  // 减小和的值
                }
            }
        }

        return result;
    }
};

算法分析:

该算法的时间复杂度为 O(n^2),其中 n 是数组的长度。在算法的主要部分,我们有两个循环嵌套,其中外层循环遍历数组的每个元素,内层循环使用双指针进行遍历。由于排序的时间复杂度为 O(n log n),所以排序操作不会成为主要的时间复杂度来源。

算法的空间复杂度为 O(1),不考虑结果的空间占用。我们只使用了常数个额外变量来存储指针和结果,没有使用额外的空间。

因此,该算法在时间和空间效率上是相对较优的解决方法。

一些拓展
三数之和问题的应用

三数之和问题在实际开发中有一些应用场景。下面是其中的一些例子:

寻找数组中和为特定值的三元组:除了题目中要求的和为0的三元组,我们也可以根据实际需求,在给定一个目标和的情况下,寻找数组中和为目标和的三元组。这个应用场景可以用在财务系统中,寻找某个特定金额的账单组合,或者在数据分析中,寻找满足某个条件的数据组合等。

寻找最接近目标值的三元组:与上述类似,我们也可以寻找和最接近目标值的三元组。在这种情况下,我们需要维护一个最小的差值,并记录对应的三元组。这个应用场景可以用在股票交易系统中,寻找最接近目标股价的买卖组合等。

寻找唯一的三元组:在题目中已经要求答案中不可以包含重复的三元组,但是在实际开发中,可能需要处理一些包含重复三元组的情况。我们可以通过一些额外的判断和去重操作,来解决这个问题。

优化思路:双指针法的进一步优化

在双指针法中,我们使用两个指针来遍历数组并查找三元组。然而,在某些情况下,我们可以通过一些优化来提高算法的效率。

在排序后的数组中,如果第一个元素大于0,那么后面的元素肯定也大于0,因此不可能存在和为0的三元组,可以直接返回空结果。

当固定第一个元素后,如果第一个元素和当前的最大和最小元素之和仍小于0,那么可以直接跳过当前元素,进入下一个循环。这是因为后面的元素更大,无法凑出和为0的三元组。

这些优化可以在算法实现中加以考虑,以提高算法的效率。文章来源地址https://www.toymoban.com/news/detail-538559.html

到了这里,关于LeetCode15.三数之和的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • (双指针 ) 15. 三数之和 ——【Leetcode每日一题】

    难度:中等 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j 、 i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请 你返回所有和为 0 且不重复的三元组。 注意 :答案中不可以包含重复的三元组。 示例 1: 输入:nums = [-1,0,1,2,-1,-4] 输出:

    2024年02月09日
    浏览(38)
  • Leetcode每日一题:15. 三数之和(2023.7.9 C++)

    目录 15. 三数之和 题目描述: 实现代码与解析: 双指针 原理思路:         给你一个整数数组  nums  ,判断是否存在三元组  [nums[i], nums[j], nums[k]]  满足  i != j 、 i != k  且  j != k  ,同时还满足  nums[i] + nums[j] + nums[k] == 0  。请 你返回所有和为  0  且不重复的三元组

    2024年02月13日
    浏览(33)
  • 【算法】排序+双指针——leetcode三数之和、四数之和

    三数之和 (1)排序+双指针   算法思路: 和之前的两数之和类似,我们对暴力枚举进行了一些优化,利用了 排序+双指针 的思路:   我们先排序,然后固定⼀个数 a ,接着我们就可以在这个数后面的区间内,使用之前两数之和使用的算法,快速找到两个数之和和固定的

    2024年02月13日
    浏览(40)
  • [双指针] (三) LeetCode LCR 179. 查找总价格为目标值的两个商品 和 15. 三数之和

    [双指针] (三) LeetCode LCR 179. 查找总价格为目标值的两个商品 和 15. 三数之和 查找总价格为目标值的两个商品 LCR 179. 查找总价格为目标值的两个商品 题目分析 (1) 数组内数字是升序 (2) 目标值为target (3) 找两数之和为target 解题思路 找两个数字的和与目标值相等,我们可以想到

    2024年02月05日
    浏览(33)
  • 【Leetcode刷题(数据结构)】:三路划分与三数随机取中的思想实现快速排序的再优化

    快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中 的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右 子序列中所有元素均大于基准值,然后最左右子序列重复该过程

    2024年02月08日
    浏览(32)
  • C++刷题第六天 454.四数相加II 383. 赎金信 15. 三数之和 18. 四数之和

    给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 = i, j, k, l n nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0 这个题目是哈希表应用的经典题目。 如果用暴力解法,四个数组,那肯定要四层for循环嵌套,时间复杂度就是n的四次方

    2024年02月13日
    浏览(36)
  • leetcode两数、三数、四数之和

    如有错误,感谢不吝赐教、交流 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按任意顺序返

    2023年04月23日
    浏览(62)
  • 算法刷题-哈希表-三数之和

    用哈希表解决了两数之和,那么三数之和呢? 力扣题目链接 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。 注意: 答案中不可以包含重复的三元组。 示例: 给定数组 nums = [-1, 0, 1, 2

    2024年02月09日
    浏览(32)
  • 【LeetCode】一起探究三数之和的奥秘

    Problem: 15. 三数之和 首先我们来分析一下本题的思路 题目说到要我们在一个整数数组中去寻找三元组,而且呢这三个数字所相加的和为 0 ,而且呢这三个数的位置还要不一样 我们以这个示例1为例来看看,我列出了3种可能性,分别是 [-1, 0, 1] 、 [-1, 2, -1] 、 [0, 1, -1] ,不过呢我

    2024年02月09日
    浏览(51)
  • 2023-07-08 LeetCode每日一题(三数之和)

    点击跳转到题目位置 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请 你返回所有和为 0 且不重复的三元组。 **注意:**答案中不可以包含重复的三元组。 提示: 3 = nums.length = 3000 -10 5

    2024年02月13日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包