当前位置: 首页 > news >正文

《算法篇:三数之和问题的两种解法》

问题描述

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

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

给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]

 解法一:哈希表法

思路

  • 首先对数组进行排序,方便后续去重操作。
  • 遍历数组,固定一个数 a 作为三元组中的第一个数。
  • 使用哈希集合来记录已经遍历过的数,对于每个固定的 a,遍历其后面的数 b,计算 c = -a - b,如果哈希集合中包含 c,则说明找到了一个满足条件的三元组。
  • 为了避免结果中出现重复的三元组,需要对 abc 进行去重处理。

代码实现

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;class Solution {public List<List<Integer>> threeSum(int[] nums) {// 用于存储最终结果的列表List<List<Integer>> result = new ArrayList<>();// 对数组进行排序,方便后续去重和处理Arrays.sort(nums);// 遍历数组,固定第一个数 nums[i]for (int i = 0; i < nums.length; i++) {// 如果第一个元素大于零,由于数组已经排序,后面的数也都大于零,不可能凑成和为零的三元组if (nums[i] > 0) {return result;}// 三元组元素 a 去重// 如果当前元素和前一个元素相同,跳过当前元素,避免重复结果if (i > 0 && nums[i] == nums[i - 1]) {continue;}// 用于存储已经遍历过的数的哈希集合HashSet<Integer> set = new HashSet<>();// 从 i+1 开始遍历数组,寻找第二个数 nums[j]for (int j = i + 1; j < nums.length; j++) {// 三元组元素 b 去重// 如果当前元素和前两个元素都相同,跳过当前元素,避免重复结果if (j > i + 2 && nums[j] == nums[j - 1] && nums[j - 1] == nums[j - 2]) {continue;}// 计算第三个数 c,使得 a + b + c = 0int c = -nums[i] - nums[j];// 如果哈希集合中包含 c,说明找到了一个满足条件的三元组if (set.contains(c)) {// 将三元组添加到结果列表中result.add(Arrays.asList(nums[i], nums[j], c));// 三元组元素 c 去重// 移除 c 以避免重复使用相同的 c 得到重复的三元组set.remove(c); } else {// 如果哈希集合中不包含 c,将当前元素 nums[j] 添加到哈希集合中set.add(nums[j]);}}}return result;}
}

复杂度分析

  • 时间复杂度:(O(n^2)),其中 n 是数组的长度。排序的时间复杂度为 (O(n log n)),两层嵌套循环的时间复杂度为 (O(n^2)),因此总的时间复杂度为 (O(n^2))。
  • 空间复杂度:(O(n)),主要用于存储哈希集合。
解法二:双指针法

思路

  • 同样先对数组进行排序。
  • 遍历数组,固定一个数 a 作为三元组中的第一个数。
  • 对于每个固定的 a,使用两个指针 left 和 right 分别指向 a 后面的元素和数组的最后一个元素。
  • 计算三个数的和 sum = a + b + c,根据 sum 的值移动指针:
    • 如果 sum > 0,说明 c 太大,将 right 指针左移。
    • 如果 sum < 0,说明 b 太小,将 left 指针右移。
    • 如果 sum == 0,说明找到了一个满足条件的三元组,将其添加到结果列表中,并对 b 和 c 进行去重处理,然后继续移动指针寻找其他可能的三元组。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;class Solution {public List<List<Integer>> threeSum(int[] nums) {// 用于存储最终结果的列表List<List<Integer>> ret = new ArrayList<>();// 对数组进行排序Arrays.sort(nums);// 遍历数组,固定第一个数 nums[i]for (int i = 0; i < nums.length; i++) {// 如果当前元素大于 0,由于数组已排序,后面的元素也都大于 0,不可能找到和为 0 的三元组,跳过此次循环if (nums[i] > 0) {continue;}// 对第一个数去重,避免结果中出现重复的三元组if (i > 0 && nums[i] == nums[i - 1]) {continue;}// 左指针,从 i+1 开始int left = i + 1;// 右指针,指向数组末尾int right = nums.length - 1;while (left < right) {// 计算三个数的和int sum = nums[i] + nums[left] + nums[right];if (sum < 0) {// 和小于 0,左指针右移,增大和left++;} else if (sum > 0) {// 和大于 0,右指针左移,减小和right--;} else {// 找到和为 0 的三元组,添加到结果列表ret.add(Arrays.asList(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--;}}}return ret;}
}

复杂度分析

  • 时间复杂度:(O(n^2)),其中 n 是数组的长度。排序的时间复杂度为 (O(n log n)),外层循环遍历数组一次,内层双指针遍历数组一次,总的时间复杂度为 (O(n^2))。
  • 空间复杂度:(O(log n)) 或 (O(n)),取决于排序算法的实现。一般来说,快速排序的空间复杂度为 (O(log n))

总结

       哈希表法利用哈希集合来记录已经遍历过的数,通过查找哈希集合来判断是否存在满足条件的三元组,实现相对简单,但需要额外的空间来存储哈希集合。

         双指针法通过排序和双指针的移动来寻找满足条件的三元组,不需要额外的空间存储哈希集合,空间复杂度较低,是一种更优的解法。

在实际应用中,建议优先使用双指针法来解决三数之和问题。

相关文章:

《算法篇:三数之和问题的两种解法》

问题描述 给定一个包含 n 个整数的数组 nums&#xff0c;判断 nums 中是否存在三个元素 a&#xff0c;b&#xff0c;c &#xff0c;使得 a b c 0 &#xff1f;找出所有满足条件且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组。 给定数组 nums [-1, 0,…...

【2025】基于springboot+uniapp的乡村旅游小程序系统统(源码、万字文档、图文修改、调试答疑)农家乐预约

乡村旅游小程序系统通过 Spring Boot 与 uniapp 技术栈的深度整合&#xff0c;为乡村旅游产业打造了一个功能全面、交互流畅、性能稳定的综合服务平台。系统根据不同角色&#xff08;管理员、商家、用户&#xff09;的业务需求&#xff0c;提供了针对性的功能模块&#xff0c;实…...

DeepSeek Kimi详细生成PPT的步骤

以下是使用 DeepSeek 和 Kimi 协作生成 PPT 的详细步骤&#xff0c;结合了两者的优势实现高效创作&#xff1a; 第一步&#xff1a;使用 DeepSeek 生成 PPT 大纲或内容 明确需求并输入提示词 在 DeepSeek 的对话界面中&#xff0c;输入具体指令&#xff0c;要求生成 PPT 大纲或…...

【Film】MM-StoryAgent:沉浸式叙事故事书视频生成,具有跨文本、图像和音频的多代理范式

MM-StoryAgent:沉浸式叙事故事书视频生成,具有跨文本、图像和音频的多代理范式 https://arxiv.org/abs/2503.05242 MM-StoryAgent: Immersive Narrated Storybook Video Generation with a Multi-Agent Paradigm across Text, Image and Audio The rapid advancement of larg…...

Tweak Power:全方位电脑系统优化的高效工具

在日常使用电脑时&#xff0c;系统性能的下降、垃圾文件的堆积以及硬盘的老化等问题常常困扰着用户。为了提升电脑性能、优化系统运行&#xff0c;许多人会选择系统优化工具。然而&#xff0c;国内一些系统优化软件常常因为广告过多或功能冗杂而让人望而却步。此时&#xff0c;…...

LVDS系列3:Xilinx的IOBUFDS原语

前面两节讲解了差分转单端的IBUFDS原语和单端转差分的OBUFDS原语&#xff0c;今天来讲一个同时带有两者功能的原语IOBUFDS&#xff1b; 前述的IBUFDS原语只能接收外部差分信号&#xff0c;此时连接管脚为input管脚&#xff0c;OBUFDS只能向外部输出差分信号&#xff0c;此时连接…...

Git和GitHub基础教学

文章目录 1. 前言2. 历史3. 下载安装Git3.1 下载Git3.2 安装Git3.3 验证安装是否成功 4. 配置Git5. Git基础使用5.1 通过Git Bash使用5.1.1 创建一个新的仓库。5.1.1.1 克隆别人的仓库5.1.1.2 自己创建一个本地仓库 5.1.2 管理存档 5.2 通过Visual Studio Code使用 6. Git完成远…...

Django-ORM-select_related

Django-ORM-select_related 作用使用场景示例无 select_related 的查询有 select_related 的查询 如何理解 "只发起一次查询&#xff0c;包含所有相关作者信息"1. select_related 的工作原理2. 具体示例解析3. 为什么只发起一次查询 数据库中的books量巨大&#xff0…...

蓝桥杯 k倍区间

题目描述 给定一个长度为 NN 的数列&#xff0c;A1,A2,⋯ANA1​,A2​,⋯AN​&#xff0c;如果其中一段连续的子序列 Ai,Ai1,⋯AjAi​,Ai​1,⋯Aj​ ( i≤ji≤j ) 之和是 KK 的倍数&#xff0c;我们就称这个区间 [i,j][i,j] 是 K 倍区间。 你能求出数列中总共有多少个 KK 倍区间…...

数据结构(蓝桥杯常考点)

数据结构 前言&#xff1a;这个是针对于蓝桥杯竞赛常考的数据结构内容&#xff0c;基础算法比如高精度这些会在下期给大家总结 数据结构 竞赛中&#xff0c;时间复杂度不能超过10的7次方&#xff08;1秒&#xff09;到10的8次方&#xff08;2秒&#xff09; 空间限制&#x…...

Tomcat+Servlet运行后出现404错误解决方案

TomcatServlet运行后出现404错误解决方案 一、错误效果复现 后续的解决方案&#xff0c;仅仅针对我遇到的情况。对不能涵盖大部分情况感到抱歉。 二、错误分析 先看看源代码&#xff1f; package com.example.secondclass.Servlet; import java.io.*; import jakarta.servl…...

论文摘要生成器:用TextRank算法实现文献关键信息提取

我们基于python代码&#xff0c;使用PyQt5创建图形用户界面&#xff08;GUI&#xff09;&#xff0c;同时支持中英文两种语言的文本论文文献关键信息提取。 PyQt5&#xff1a;用于创建GUI应用程序。 jieba&#xff1a;中文分词库&#xff0c;用于中文文本的处理。 re&#xff…...

Flutter中网络图片加载显示Image.network的具体用法

Image.network的具体用法 Image.network 是 Flutter 中用于从网络加载图片的便捷方法。它基于 NetworkImage&#xff0c;可以快速加载并显示网络图片。以下是 Image.network 的具体用法和常见参数说明。 基本用法 最简单的用法是提供一个图片的 URL&#xff1a; dart 复制 …...

【HarmonyOS Next】鸿蒙应用故障处理思路详解

【HarmonyOS Next】鸿蒙应用崩溃处理思路详解 一、崩溃问题发现后定位 1. 崩溃现象&#xff1a; 常见的崩溃问题表现为&#xff0c;应用操作后白屏闪退&#xff0c;或者应用显示无响应卡死。 2.定位问题&#xff1a; 发现崩溃后&#xff0c;我们首先需要了解复现步骤&#x…...

狮子座大数据分析(python爬虫版)

十二星座爱情性格 - 星座屋 首先找到一个星座网站&#xff0c;作为基础内容&#xff0c;来获取信息 网页爬取与信息提取 我们首先利用爬虫技术&#xff08;如 Python 中的 requests 与 BeautifulSoup 库&#xff09;获取页面内容。该页面&#xff08;xzw.com/astro/leo/&…...

QT系列教程(18) MVC结构之QItemSelectionModel模型介绍

视频教程 https://www.bilibili.com/video/BV1FP4y1z75U/?vd_source8be9e83424c2ed2c9b2a3ed1d01385e9 QItemSelectionModel Qt的MVC结构支持多个View共享同一个model&#xff0c;包括该model的选中状态等。我们可以通过设置QItemSelectionModel&#xff0c;来更改View的选…...

git设置本地仓库和远程仓库

设置本地仓库和远程仓库是使用Git进行版本控制的基本操作。以下是详细步骤&#xff1a; 创建本地仓库 初始化本地仓库&#xff1a; 打开命令行工具&#xff08;如Terminal或Git Bash&#xff09;。导航到你希望创建Git仓库的项目文件夹。运行以下命令来初始化一个新的Git仓库&…...

openharmony中HDF驱动框架源码梳理-驱动加载流程

要想大概了解一个公司&#xff0c;我们可能只需要知道它的运行逻辑即可&#xff0c;例如我们只需要知道它有财务有研发有运营等&#xff0c;财务报销、研发负责产品等即可&#xff0c;但是如果想深入具体的了解的话我们就要了解都有什么部门(对象)、各部门都包含哪些职责(对象方…...

golang 高性能的 MySQL 数据导出

需求导出方式对比方案1:快照导出(耗时:1.5s)方案2: 偏移分页(耗时:4s)方案 3:普通分页(耗时:4min40s) 需求 导出 MySQL 数据 分析: 一次性 select 大量数据带来的问题 性能问题&#xff1a; 数据库负载&#xff1a;大量数据查询会增加数据库的CPU、内存和I/O负担&#xff…...

31-判断子序列

给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相对位置形成的新字符串。&#xff08;例如&#xff0c;"ace"是"abcde"的一个子序列&#x…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

(一)单例模式

一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)

LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 题目描述解题思路Java代码 题目描述 题目链接&#xff1a;LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...

LangFlow技术架构分析

&#x1f527; LangFlow 的可视化技术栈 前端节点编辑器 底层框架&#xff1a;基于 &#xff08;一个现代化的 React 节点绘图库&#xff09; 功能&#xff1a; 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...