LeetCode题练习与总结:三数之和

一、题目

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

请你返回所有和为 0 且不重复的三元组。

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

二、解题思路

  1. 排序数组:首先,我们需要对数组进行排序。这样可以帮助我们在后续步骤中更有效地找到满足条件的三元组。

  2. 遍历数组:然后,我们遍历数组,对于每个元素 nums[i],我们使用两个指针,一个指向当前元素的下一个元素(左指针),另一个指向数组的最后一个元素(右指针)。

  3. 双指针法:对于当前元素 nums[i],我们尝试找到两个其他元素,使得这三个元素的和为0。我们移动左指针和右指针,使得左指针指向的元素和右指针指向的元素的和加上当前元素 nums[i] 是否等于0。如果和小于0,我们向右移动左指针;如果和大于0,我们向左移动右指针。这样我们可以保证在每一步中,我们都在寻找和为0的三元组。

  4. 去重:在找到满足条件的三元组后,我们需要确保返回的结果中不包含重复的三元组。这可以通过在添加三元组到结果列表之前检查是否已经存在相同的三元组来实现。

  5. 返回结果:最后,我们返回包含所有满足条件的三元组的列表。

三、具体代码

import java.util.ArrayList;
import java.util.List;class Solution {public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> result = new ArrayList<>();if (nums == null || nums.length < 3) {return result;}// Step 1: Sort the arrayArrays.sort(nums);// Step 2: Iterate through the arrayfor (int i = 0; i < nums.length - 2; i++) {// To avoid duplicates, we skip the same elementif (i > 0 && nums[i] == nums[i - 1]) {continue;}// Step 3: Use two pointersint left = i + 1;int right = nums.length - 1;while (left < right) {int sum = nums[i] + nums[left] + nums[right];// Check if the sum is 0if (sum == 0) {// Add the triplet to the result set and move both pointersresult.add(Arrays.asList(nums[i], nums[left], nums[right]));// Skip duplicateswhile (left < right && nums[left] == nums[left + 1]) {left++;}while (left < right && nums[right] == nums[right - 1]) {right--;}left++;right--;} else if (sum < 0) {// If sum is less than 0, move left pointer to the rightleft++;} else {// If sum is greater than 0, move right pointer to the leftright--;}}}return result;}
}

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 排序数组O(n log n),因为数组排序通常使用快速排序、归并排序等,其平均时间复杂度为 O(n log n)
  • 遍历数组O(n),因为我们只需要遍历数组一次。
  • 双指针法:在最坏的情况下,对于数组中的每个元素,双指针可能需要遍历剩余的数组元素,这在最坏情况下是 O(n^2)。但是,由于我们在找到和为0的三元组后会移动指针,所以实际的时间复杂度会小于 O(n^2)。具体来说,每次移动左指针或右指针时,我们都会跳过重复的元素,这减少了实际的比较次数。

综合考虑,时间复杂度可以近似为 O(n^2),因为排序是预处理步骤,而双指针法是主要的时间消耗部分。

2. 空间复杂度
  • 结果列表:在最坏的情况下,如果数组中的所有元素都满足三元组和为0的条件,那么结果列表的大小将是 O(n^2)。这是因为我们可能会添加 n * (n - 1) / 2 个三元组到结果列表中(假设数组中的元素都是唯一的)。
  • 辅助空间:除了结果列表,我们还需要额外的空间来存储排序后的数组索引(即左指针和右指针),这在最坏情况下是 O(1)

所以,空间复杂度是 O(n^2)(结果列表)加上 O(1)(指针),可以简化为 O(n^2)

请注意,这里的分析是基于最坏情况的假设。在实际应用中,由于数组中可能存在负数、正数和零,且它们的分布可能不均匀,实际的时间复杂度可能会有所不同。

五、总结知识点

1. 数组排序

  • 使用 Arrays.sort(nums) 方法对整数数组进行排序。这是 Java 标准库中的一个方法,用于对数组进行快速排序。

2. 数组遍历

  • 使用 for 循环遍历数组,这是 Java 中常见的迭代数组元素的方法。

3. 条件判断

  • 在遍历过程中,使用 if 语句跳过重复的元素,以避免在结果中出现重复的三元组。

4. 双指针技巧

  • 使用两个指针(leftright)来遍历数组的剩余部分,这是一种高效的算法技巧,用于在有序数组中寻找特定条件的元素组合。

5. 列表操作

  • 使用 ArrayListArrays.asList() 方法来创建和添加列表元素。ArrayList 是 Java 中的一个动态数组,可以动态地添加和删除元素。

6. 去重处理

  • 在添加三元组到结果列表之前,通过移动指针来跳过重复的元素,这是一种常见的去重策略。

7. 逻辑控制

  • 使用 while 循环结合条件判断(if-else)来控制指针的移动,这是解决这类问题的关键逻辑。

8. 返回结果

  • 最后,将包含所有满足条件的三元组的列表返回给调用者。

9. 时间复杂度和空间复杂度分析

  • 虽然代码中没有直接展示,但理解时间复杂度和空间复杂度对于优化算法和评估算法效率是非常重要的。

10. 代码风格

  • 代码遵循了一定的命名规范和结构,如方法名 threeSum 清晰地表达了其功能,变量名如 resultleftright 等也直观地反映了它们的用途。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

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

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

相关文章

【数学建模规则】2024年第九届数维杯大学生数学建模挑战赛参赛指南

一、竞赛介绍 数维杯大学生数学建模挑战赛每年分为两场&#xff0c;每年上半年为数维杯国赛&#xff08;5月&#xff0c;俗称小国赛&#xff09;&#xff0c;下半年为数维杯国际赛(11月)&#xff0c;2023年第八届数维杯大学生数学建模挑战赛共有近1.4万名学生参赛&#xff0c;…

Unity之PUN2插件实现多人联机射击游戏

目录 &#x1f4d6;一、准备工作 &#x1f4fa;二、UI界面处理 &#x1f4f1;2.1 登录UI并连接PUN2服务器 &#x1f4f1;2.2 游戏大厅界面UI &#x1f4f1;2.3 创建房间UI &#x1f4f1;2.4 进入房间UI &#x1f4f1;2.5 玩家准备状态 &#x1f4f1;2.6 加载战斗场景…

vue proxy解决跨域问题

https://blog.csdn.net/tttttrrrhh/article/details/127685318 cims系统ui

java 面向对象-上:类的结构之二

类的设计中&#xff0c;两个重要结构之二&#xff1a;方法 方法 描述类应该具的功能。 比如&#xff1a;Math类&#xff1a;sqrt()\random() \... Scanner类&#xff1a;nextXxx() ... Arrays类&#xff1a;sort() \ binarySearch() \ toString() \ equals() \ ... 1.举例 p…

【nginx作为缓存服务器】

目录 一、Nginx缓存介绍二、Nginx配置缓存1.缓存开关:proxy_cache2.代理缓存:proxy_cache_path4.缓存过期 一、Nginx缓存介绍 Nginx可以对浏览器缓存进行配置&#xff0c;让一些静态资源缓存到用户本地存储&#xff0c;以提高页面的响应速度&#xff0c;也能降低服务端的压力&…

c入门第二十一篇: 学生成绩管理系统之成绩排序

前言 在学生成绩管理系统中&#xff0c;必然面临着排序的问题。这里我们简单的将之前讲过的冒泡排序应用于我们的学生成绩管理系统中。 冒泡排序是一种简单的排序算法&#xff0c;它重复地遍历要排序的列表&#xff0c;比较相邻的两个项&#xff0c;如果相邻不是预期的顺序时交…

[Java 项目亮点] 三层限流设计

思路来源&#xff1a;bilibili 河北王校长 文章目录 面试官可能会问你能详细介绍一下Nginx的http_limit_req_module模块吗&#xff1f;你能解释一下如何在Nginx中配置http_limit_req_module模块吗&#xff1f;你知道如何调整Nginx的http_limit_req_module模块以适应不同的业务需…

【服务器数据恢复】通过reed-solomon算法恢复raid6数据的案例

服务器数据恢复环境&#xff1a; 一台网站服务器中有一组由6块磁盘组建的RAID6磁盘阵列&#xff0c;操作系统层面运行MySQL数据库和存放一些其他类型文件。 服务器故障&#xff1a; 该服务器在工作过程中&#xff0c;raid6磁盘阵列中有两块磁盘先后离线&#xff0c;不知道是管理…

Linux--自定义shell

shell shell就是操作系统提供给用户与操作系统进行交互的命令行界面。它可以理解为一个用户与操作系统之间的接口&#xff0c;用户可以通过输入命令来执行各种操作&#xff0c;如文件管理、进程控制、软件安装等。Shell还可以通过脚本编程实现自动化任务。 常见的Unix系统中使…

华为机试真题实战应用【算法代码篇】-报文回路(附python、C++和JAVA代码实现)

目录 问题描述 输入描述 输出描述 样例 组播协议-IGMP 1.IGMPv1基本概念

创新性3D数据合成模型,微软推出EgoGen

随着AR、VR等设备的广泛应用,第一人称的应用开始增多。但在研发方面面临不同的挑战,例如&#xff0c;图像模糊、视觉混乱、遮挡更严重等&#xff0c;给视觉模型的训练带来重大挑战。 一方面,人工标注真实第一视角数据集&#xff0c;来培训深度学习模型的成本和难度都很高。另一…

Java 泛型

优质博文&#xff1a;IT-BLOG-CN 一、为什么要有泛型 【1】解决元素存储的安全性问题。 【2】解决获取数据元素时&#xff0c;需要类型强转的问题。 【3】可以统一数据类型&#xff0c;便于操作。 【4】将运行时的异常提前到了编译时&#xff0c;提高了效率。 【5】实现代码的…

Day20_网络编程(软件结构,网络编程三要素,UDP网络编程,TCP网络编程)

文章目录 Day20 网络编程学习目标1 软件结构2 网络编程三要素2.1 IP地址和域名1、IP地址2、域名3、InetAddress类 2.2 端口号2.3 网络通信协议1、OSI参考模型和TCP/IP参考模型2、UDP协议3、TCP协议 2.4 Socket编程 3 UDP网络编程3.1 DatagramSocket和DatagramPacket1、Datagram…

关于地址引用与值引用的坑

List<UserInfo> userInfoList new List<UserInfo>(); List<UserInfo> userInfoList_new new List<UserInfo>(userInfoList);userInfoList_new 与userInfoList 指的是相同的内存吗&#xff1f; 答&#xff1a; 在C#中&#xff0c;userInfoList_new …

小世界网络:直径、分形、同配性

1.小世界网络特点 —— 网络直径接近于网络中节点数量的自然对数 2.小世界分形网络 —— 移除弱链接的小世界网络 3.同配性分析 —— Pearson相关系数、邻居相关度 在宏观层面上&#xff0c;关注平均度、度分布和聚类等全局结构特征的影响。更高的平均度被认为会导致更…

Zookeeper简介及选举机制

1.概述 Zookeeper是一个开源的&#xff0c;分布式的&#xff0c;为分布式框架&#xff08;如下图中的Hadoop和Hive&#xff09;提供协调服务的Apache项目。 工作机制&#xff1a;基于观察者设计模式的分布式服务管理框架&#xff0c;负责存储和管理数据&#xff0c;接受观察者…

[算法沉淀记录] 排序算法 —— 归并排序

排序算法 —— 归并排序 算法介绍 归并排序是一种分治算法&#xff0c;由约翰冯诺伊曼在1945年发明。它的工作原理是将未排序的列表划分为n个子列表&#xff0c;每个子列表包含一个元素(包含一个元素的列表被认为是有序的)&#xff0c;然后重复合并子列表以生成新的有序子列表…

ClickHouse 指南(三)最佳实践 -- 稀疏主索引

在ClickHouse主索引的实用介绍 ClickHouse release 24.1, 2024-01-30 1、简介 在本指南中&#xff0c;我们将深入研究ClickHouse索引。我们将详细说明和讨论: ClickHouse中的索引与传统的关系数据库管理系统有何不同ClickHouse是如何构建和使用表的稀疏主索引的什么是在Clic…

JavaScript原型继承与面向对象编程思想

原型继承与面向对象编程思想 在JavaScript中&#xff0c;原型(prototype)、构造函数(constructor)和实例对象(instance)是面向对象编程中的重要概念&#xff0c;并且它们之间存在着紧密的关系。 原型(prototype)&#xff1a;原型是JavaScript中对象之间关联的一种机制。每个Ja…

js使用import到本js文件中的函数时报错 Error [ERR_MODULE_NOT_FOUND]: Cannot find module

node:internal/process/esm_loader:97internalBinding(errors).triggerUncaughtException(^Error [ERR_MODULE_NOT_FOUND]: Cannot find module D:\桌面\Pagesizedetection\lib\screensize imported from D:\桌面\Pagesizedetection\index.js Did you mean to import ../lib/sc…