题目描述

原题链接

给你一个整数数组 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 。

解题思路

1. 初步分析

要找三元组,最原始最暴力的方法就是三层遍历,时间复杂度 O(n^3)。但就像双指针可以把二维遍历降为一维遍历一样,使用双指针也可以把三维遍历降为二维的。

2. 三指针解法

基本思路:

  • 使用三个指针 i、j、k,i 指针指示三元组的第一个数,j 指针和 k 指针相向移动,分别指向三元组的第二个数和第三个数。
  • 对 nums[i]、nums[j]、nums[k] 求和,根据 sum 值大小进行讨论
    • 等于 0:放入结果数组,j、k 同时移动
    • 小于 0:移动 j
    • 大于 0:移动 k

去重逻辑:

  • i 位去重

    //检查下标合法 && 当前i位与前一个i位(nums[i-1])相等
    if(i > 0 && nums[i] == nums[i - 1]){continue;
    }
    
  • j 位去重

    //检查下标合法 && 当前j位与前一个j位(nums[j-1])相等
    if(j > i + 1 && nums[j] == nums[j - 1]){++j;continue;
    }
    
  • k 位去重(k 是从右向左移动的)

    //检查下标合法 && 当前k位与前一个k位(nums[k+1])相等
    if(k < nums.size() - 1 && nums[k] == nums[k + 1]){--k;continue;
    }
    

**剪枝逻辑:**核心算法前对数组进行排序,若三元组第三位(即 k 位)元素大于 0,则可跳出当前双指针循环。

3. 代码主干

vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>> result;sort(nums.begin(), nums.end());//遍历i位for(int i = 0; i < nums.size() - 2; ++i){//对i为进行去重//定义j、k指针int j = i + 1, k = nums.size() - 1;while(j < k){   //利用双指针降维//剪枝//对j位进行去重//对k位进行去重//计算sum值,并对sum值进行讨论}}return result;
}

完整代码

vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>> result;sort(nums.begin(), nums.end());for(int i = 0; i < nums.size() - 2; ++i){//对i为进行去重if(i > 0 && nums[i] == nums[i - 1]){continue;}int j = i + 1, k = nums.size() - 1;while(j < k){   //利用双指针降维//剪枝if(nums[k] < 0) break;//对j位进行去重if(j > i + 1 && nums[j] == nums[j - 1]){++j;continue;}//对k位进行去重if(k < nums.size() - 1 && nums[k] == nums[k + 1]){--k;continue;}//计算sum值,并对sum值进行讨论int sum = nums[i] + nums[j] + nums[k];if(sum == 0){vector<int> tmp = {nums[i], nums[j], nums[k]};result.push_back(tmp);++j, --k;}else if(sum < 0){++j;}else if(sum > 0){--k;}}}return result;
}

关于 unordered_set 的补充

在尝试优化时浅浅使用了一下 unordered_set<vector<int>>,编译报错:

Line 6: Char 36: error: call to implicitly-deleted default constructor of 'unordered_set<vector<int>>'unordered_set<vector<int>> result;

搜索了一下 unordered_set 的使用方法,发现 unordered_set 容器的类模板定义如下:

template < class Key,                 //容器中存储元素的类型class Hash = hash<Key>,      //确定元素存储位置所用的哈希函数class Pred = equal_to<Key>, //判断各个元素是否相等所用的函数class Alloc = allocator<Key>    //指定分配器对象的类型> class unordered_set;

逐个分析:

  1. **容器中存储元素的类型:**在 unordered_set 中,key 和 value 的类型都是一致的,指的就是 key 的类型
  2. **确定元素存储位置所用的哈希函数:**指定元素存储位置的哈希函数,注意:默认哈希函数 hash<Key> 只适用于基本数据类型(包括 string 类型),而不适用于自定义的结构体或者类。比如说 vector<int> 不属于基本数据类型。
  3. **判断各个元素是否相等所用的函数:**unordered_set 容器内部不能存储相等的元素,而衡量 2 个元素是否相等的标准,取决于该参数指定的函数。 默认情况下,使用 STL 标准库中提供的 equal_to<key> 规则,该规则仅支持可直接用 == 运算符做比较的数据类型。
  4. 指定分配器对象的类型:略

[230420 leetcode15] 三数之和相关推荐

  1. LeetCode15. 三数之和 16. 最接近的三数之和

    LeetCode15. 三数之和 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组 ...

  2. [Swift]LeetCode15. 三数之和 | 3Sum

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ ➤微信公众号:山青咏芝(shanqingyongzhi) ➤博客园地址:山青咏芝(https://www.cnblog ...

  3. leetcode15. 三数之和(三指针)

    一:题目 二:思路 1.这里的去重是指的是我们在遍历元素的时候,遇到相同的挨着的相同的元素的时候要跳过 2.对元素进行排序,为了后面的比较 3.我们用的是三个指针,第一个指针i指向第一个元素,第二个指 ...

  4. leetcode15 三数之和

    给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复的三元组. ...

  5. leetcode15. 三数之和(详解)

    一:题目 二:上码 class Solution {public:/**思路:1.这个题出其不意之处在于,其先对这个序列进行了排序排序的好处是1>:如果首元素是大于0的,那么如果无论无何也凑不出 ...

  6. Leetcode--15. 三数之和

    给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复的三元组. ...

  7. LeetCode--15.三数之和

    给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j.i != k 且 j != k ,同时还满足 nums[i] + nums ...

  8. 【LeetCode15】三数之和

    三数之和 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组. 注意:答案中不可以包含 ...

  9. LeetCode 15. 三数之和(3Sum)

    15. 三数之和 15. 3Sum 题目描述 Given an array nums of n integers, are there elements a, b, c in nums such th ...

最新文章

  1. 自动驾驶平台,阵营, 主要传感器与场景联系
  2. 依赖类型dependency type在maven中的作用
  3. onethink封装arclist调用文章列表!
  4. 2013年国家计算机一级考试试题,2013年计算机一级的考试试题.doc
  5. Spring Boot –现代Java应用程序的基础
  6. 基于matlab的ldpc编码的构造,基于LDPC编码的GMSK调制与解调及matlab仿真实现(含录像)...
  7. css 多栏文字流 css two columns text flow
  8. PHP特级课视频教程_第三十四集 Mongodb性能优化_李强强
  9. 29.Linux/Unix 系统编程手册(上) -- 线程:介绍
  10. DSP28335定时器
  11. 20210422-微信刷脸支付获取调用凭证authinfo的时候,提示 rawdata无效
  12. WIN10_用户获取最高的管理员权限(关闭UAC控制)
  13. Layabox 屏幕适配
  14. HttpHeaders()无法调用
  15. 《单片机原理及应用(魏洪磊)》第七章第8题
  16. 【JZOJ4598】准备食物
  17. 网易企业邮箱:三道防御、七项措施,切实保障企业邮箱安全【企业邮箱申请】
  18. Oracle数据库实例之内存架构(一)
  19. 千年服务器经验怎么修改,千年服务端加入江湖等级的脚本
  20. 高新技术企业申请容易吗?如何提高申报通过的机率?

热门文章

  1. landa表达式的一点东西
  2. js遍历对象key,value
  3. 8-vulnhub靶机-IMF-缓冲区提权
  4. 豆瓣上备受好评的21本Python书籍大集合【墙裂推荐收藏】
  5. 电商API 接口用途详解,接口大全(商品、订单、搜索、SKU、上下架)
  6. Python告诉你想开一家美食店该怎么做
  7. Emacs 窗体的透明设置
  8. Python中怎么换行?
  9. 一文搞懂基础数据单位换算逻辑
  10. LeetCode-Python 栈专题(学习笔记+代码)