LeetCode题目笔记——15. 三数之和

news2024/11/17 14:35:02

文章目录

    • 题目描述
    • 题目链接
    • 题目难度——中等
    • 方法一:暴力(参考)
      • 代码/Python 参考
    • 方法二:哈希
      • 代码/Python参考
    • 方法三:排序+双指针
      • 代码/Python
      • 代码/C++
    • 总结

题目描述

龙门阵:这个n个数之和是不是有什么深意啊,好几个这种题,这个题虽然标的是中等,但我咋觉得考思维考得像困难一样。这个题跟两数之和还有点想,没看过两数之和的伙伴可以看我这篇LeetCode题目笔记——1.两数之和
前两种方法都会超时,仅供参考和自己记录,小伙伴可以跳过,直接到方法三。

给你一个整数数组 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]
输出:[[-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

题目链接

题目难度——中等

方法一:暴力(参考)

  根据提示,数据的长度最多也只有3000,所以我们可以尝试暴力一下,但是注意,虽然理论上可以暴力,但是三重循环的话,最坏情况下将会执行30003 = 2.7 * 1010 次比较,同时答案也可能会有这么多,因此其时间和空间复杂度都非常高,到了这个量级就不能暴力了,而且在这过程中还要考虑到元素的去重问题,所以仅限于在本地跑着玩。

代码/Python 参考

class Solution:
    def threeSum(self, nums: list[int]) -> list[list[int]]:
    	res = []
    	n = len(nums)
    	for i in range(n):
    		for j in range(n):
    			for k in range(n):
    				if i != j and i != k and k != j and nums[i] + nums[j] + nums[k] == 0:
    					 res.append([nums[i], nums[j], nums[k])
    	# 去重略
    	return res
    	

方法二:哈希

  前面说过这题和两数之和有点像,所以我们还可以把问题转换为对数组中的每个x,将其作为target,求剩余元素中的两数之和问题。如果用两数之和中哈希表的做法,时间复杂度可以降到O(N2),但同时还要考虑到如何进行元素去重的问题,所以仍然可能会超时。

代码/Python参考

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        # 转换为两数之和问题
            res = defaultdict(int)
            ans = []
            pos = dict()
            for i, x in enumerate(nums):
                target = 0 - x
                for j, y in enumerate(nums):
                    if i != j:
                        tmp = target - y
                        if tmp in pos and pos[tmp] != j and pos[tmp] != i:
                            res[tuple(sorted([x, y, tmp]))] += 1
                        else:
                            pos[y] = j
        	# 用字典的键实现去重
            return list(map(list, res.keys()))

方法三:排序+双指针

  前面提到的去重问题,我觉得也是本题的考点之一,那我们让每个答案三元组(a,b,c)都是非递减的,同时三元组整体也是非递减的,那不就能保证答案不会重复了吗,所以我们先排序原数组,同时用上一个方法的思想,将每个x都视为一次target,然后使用双指针的方法找到答案。具体的解释见代码里:

代码/Python

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        res = []
        nums.sort()
        n = len(nums)
        pre = 1000001
        for i in range(n):
            if nums[i] == pre:      # 保证不重复
                continue
            if nums[i] > 0:         # 排序后,a>0,后面不可能有b,c使得a+b+c=0
                break
            pre = nums[i]
            a = nums[i]
            target = -a         # 每个target=-a
            p2 = n - 1          # 后指针
            p1pre = 1000001
            for p1 in range(i + 1, n - 1):      #前指针
                if p1pre == nums[p1]:           # 保证不重复
                    continue
            
                b = nums[p1]
                p1pre = b
                while p1 < p2:
                    c = nums[p2]
                    if b + c < target:  # 保证前指针的数先找完
                        break
                    elif b + c > target:    
                        p2 -= 1
                    else:
                        res.append([a, b, c])
                        p2 -= 1
                        break           # 找到一个答案,退出while,让前指针后移
    
        return res

在这里插入图片描述

代码/C++

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> res;
        sort(nums.begin(), nums.end());
        int n = nums.size(), pre, p1pre, i, target, a, b, c, p1, p2;
        pre = 1000001;
        for(i = 0; i < n; i++){
            if(nums[i] == pre){
                continue;
            }
            if(nums[i] > 0){
                break;
            }
            a = nums[i];
            pre = a;
            target = -a;
            p2 = n - 1;
            for(p1 = i + 1; p1 < n; p1++){
                if(p1pre == nums[p1]){
                    continue;
                }
                b = nums[p1];
                p1pre = b;
                while(p1 < p2){
                    c = nums[p2];
                    if(b + c < target){
                        break;
                    }
                    else if(b + c > target){
                        p2--;
                    }
                    else{
                        res.push_back({a, b, c});
                        p2--;
                        break;
                    }
                }
            }
        }
        return res;
    }
};

总结

  前两种方法都是O(N3),第三种优化后是O(N2),空间上都是O(1)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/339012.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python中的类和对象(6)

文章目录1.多态2.类继承的多态3.自定义函数的多态4.鸭子类型5.思维导图1.多态 多态在编程中是一个非常重要的概念&#xff0c;它是指同一个运算符、函数或对象在不同的场景下&#xff0c;具有不同的作用效果&#xff0c;这么一个技能。 我们知道加号&#xff08;&#xff09;…

加载sklearn新闻数据集出错 fetch_20newsgroups() HTTPError: HTTP Error 403: Forbidden解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…

大数据框架之Hadoop:入门(五)Hadoop编译源码(面试重点)

5.1 前期准备工作 1.CentOS联网 配置CentOS能连接外网。Linux虚拟机ping www.baidu.com 是畅通的 注意&#xff1a;采用root角色编译&#xff0c;减少文件夹权限出现问题 2.jar包准备(hadoop源码、JDK8、maven、ant 、protobuf) &#xff08;1&#xff09;hadoop-2.7.7-sr…

【TCP的拥塞控制】基于窗口的拥塞控制

TCP的拥塞窗口CWND大小和传输轮次n的关系如下所示。&#xff08;本题10分&#xff09; cwnd12481632333435363738394041422122232425261248N1234567891011121314151617181920212223242526 问题&#xff1a; &#xff08;1&#xff09;慢开始阶段的时间间隔&#xff1f;&#…

NFC enable NFC使能流程

同学,别退出呀,我可是全网最牛逼的 WIFI/BT/GPS/NFC分析博主,我写了上百篇文章,请点击下面了解本专栏,进入本博主主页看看再走呗,一定不会让你后悔的,记得一定要去看主页置顶文章哦。 NFC enable NFC使能流程 认识nfc系统如何工作,最好的方法就是了解nfc的各个流程,…

linux系统下SVN服务器搭建

linux新手&#xff0c;整了好几天才搞好&#xff0c;做下笔记以备后续使用&#xff1a; 1、下载svn服务器 yum -y install subversion 2、创建仓库 svnadmin create /opt/svn/pro/respos1 svnadmin create /opt/svn/pro/respos2 3、配置用户以及权限 1:cd到仓库目录下&#…

py3常用返回规则字符串的函数+ascii与char的转换

文章目录py3常用返回规则字符串的函数字符转ascii以及ascii转字符的方法为&#xff1a;py3常用返回规则字符串的函数 注明原来的网址为&#xff1a;https://docs.python.org/3.8/library/string.html string.ascii_letters 返回所有的大写、小写字母 string.ascii_lowercase 返…

寒假安全作业nginx-host绕过实例复现

1.测试环境搭建 LNMP架构的话&#xff0c;肯定就是linux、nginx、mysql、php四大组件。在后面的复现中我们还会用到https的一部分知识&#xff0c;故这里的nginx就需要使用虚拟主机并且配置https证书&#xff0c;且具有php解析功能。 1.1 基础nginx配置 #1.创建web目录 mkdir …

MySQL-InnoDB行格式浅析

简介 我们知道读写磁盘的速度非常慢&#xff0c;和内存读写差了几个数量级&#xff0c;所以当我们想从表中获取某些记录时&#xff0c; InnoDB 存储引擎需要一条一条的把记录从磁盘上读出来么&#xff1f; 不&#xff0c;那样会慢死&#xff0c;InnoDB 采取的方式是&#xff1a…

雅思经验(十三)

感觉这篇其实有点小难&#xff0c;我在精听的才发现那是六个实验对象&#xff0c;但是叫做six subjects在精听的时候感觉有些手忙脚乱&#xff0c;像是一团乱麻一样&#xff0c;但是也是没有什么关系。其实这才是查漏补缺&#xff0c;cello player 这是大提琴师violinists 小提…

08- 数据升维 (PolynomialFeatures) (机器学习)

在做数据升维的时候&#xff0c;最常见的手段就是将已知维度进行相乘&#xff08;或者自乘&#xff09;来构建新的维度 使用 np.concatenate()进行简单的&#xff0c;幂次合并&#xff0c;注意数据合并的方向axis 1 数据可视化时&#xff0c;注意切片&#xff0c;因为数据升维…

SpringDI自动装配BeanSpring注解配置和Java配置类

依赖注入 上篇博客已经提到了DI注入方式的构造器注入&#xff0c;下面采用set方式进行注入 基于set方法注入 public class User {private String name;private Address address;private String[] books;private List<String> hobbys;private Map<String,String>…

【Linux】多线程编程 - 概念/pthread库调用接口/互斥

目录 一.线程概念 1.Linux中线程如何实现 2.POSIX线程库: pthread第三方线程库 3.线程与进程的数据存放问题 4.线程的"高效"具体体现在哪 5.线程优缺点 二.线程控制 0.关于pthread_t类型 1.线程创建 2.线程终止 3.线程等待 4.线程分离 5.代码验证 三.线…

你期待已久的《动手学深度学习》(PyTorch版)来啦!

《动手学深度学习》全新PyTorch版本&#xff0c;李沐和亚马逊科学家阿斯顿张等大咖作者强强联合之作&#xff0c;机器学习、深度学习领域重磅教程&#xff0c;交互式实战环境&#xff0c;配套资源丰富&#xff01; 面向中文读者的能运行、可讨论的深度学习入门书。 动手学深度…

一个优质软件测试工程师简历的范文(一定要收藏)

很多刚转行软件测试的小伙伴是不是不知道怎么写好一份优质的软件测试工程师的简历。今天呢&#xff0c;就给大家分享一下一个优质软件测试工程师简历的范文。记得收藏起来哦。 下面的案例&#xff1a;2-3年的软件测试工程的简历 姓 名&#xff1a;XXX 学历&#xff1a…

2023备战金三银四,Python自动化软件测试面试宝典合集(五)

接上篇八、抓包与网络协议8.1 抓包工具怎么用 我原来的公司对于抓包这块&#xff0c;在 App 的测试用得比较多。我们会使用 fiddler 抓取数据检查结果&#xff0c;定位问题&#xff0c;测试安全&#xff0c;制造弱网环境;如&#xff1a;抓取数据通过查看请求数据&#xff0c;请…

FPGA实现不同分辨率视频切换输出,串口协议帧控制,提供工程源码和技术支持

目录1、不同分辨率视频切换输出原理2、设计思想和架构详解3、vivado工程详解4、上板调试验证并演示5、福利&#xff1a;工程代码的获取1、不同分辨率视频切换输出原理 不同分辨率的视频输出对应不同的时序和时钟&#xff0c;一般情况下是不存在同时或分时输出的&#xff0c;但…

结构体变量

C语言允许用户自己建立由不同类型数据组成的组合型的数据结构&#xff0c;它称为结构体&#xff08;structre&#xff09;。 在程序中建立一个结构体类型&#xff1a; 1.结构体 建立结构体 struct Student { int num; //学号为整型 char name[20]; //姓名为字符串 char se…

基于spring boot +opencv 实现车牌识别、人脸识别、证件识别等功能 附完整代码 毕业设计

界面展示: 这是一个基于spring boot + opencv 实现的项目贯穿样本处理、模型训练、图像处理、对象检测、对象识别等技术点以学习交流为目的&

装满杯子需要的最短总时长-力扣2335-java双百方案

一、题目描述 现有一台饮水机&#xff0c;可以制备冷水、温水和热水。每秒钟&#xff0c;可以装满 2 杯 不同 类型的水或者 1 杯任意类型的水。 给你一个下标从 0 开始、长度为 3 的整数数组 amount &#xff0c;其中 amount[0]、amount[1] 和 amount[2] 分别表示需要装满冷水…