【Leetcode】《双指针出击:多数和问题的“破阵之匙”,解锁高效算法密码》

前言

🌟🌟本期讲解关于双指针解决多数和问题~~~

🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客

🔥 你的点赞就是小编不断更新的最大动力                                       

🎆那么废话不多说直接开整吧~~

目录

📚️1.和为s的两个数

1.1题目描述

1.2题目解析

1.暴力枚举

2.双指针

1.3题目代码 

1.暴力枚举

2.双指针

📚️2.三数之和

2.1题目描述

2.2题目解析

1.暴力枚举

2.双指针

2.3题目代码

📚️3.总结


 

📚️1.和为s的两个数

1.1题目描述

本题的题目要求就是给定一个目标数,然后在数组内,找到两个数,使得这两个数的和为目标数;

题目展示如下:

很明显,就是找到两个数,然后等于目标数即可,此时的输出的顺序是不用过多担心的~~~

1.2题目解析

1.暴力枚举

思路:

这种做法就是直接两层for循环,直接开始遍历,然后直接相加,判断是否等于目标数,若等于直接拿出这两个数,反之遍历完了,还是没有,直接返回-1;

优点:快速,容易想到,直接上手,没有坑~~

缺点:时间复杂度比较高,效率降低~~~

具体的图片实例如下:

可以看到此时就是一个数一个数遍历,然后每次循环结束后,重上一个规定的数加1,再次继续循环遍历相加~~~

2.双指针

这里的思路就是通过利用双指针的思想进行操作,此时主要是利用题目的中的条件,即数组内的数字是顺序排序的;那么我们就可以利用这一点;

思路:

这里的思路就是:先规定一个两个指针子在数组的0号下标,一个在最后一个数字下标,注意了,由于数组是顺序排序的,那么当两个数和大于规定数,那么就移动右边的指针,使数字变小,由于左边已经是最小的了,那么就不应该移动,一旦移动就会变得更大;

具体到图示如下:

可以看到,此时由于两个数字之和大于目标数,那么就直接移动right指针,使和变小,若大于了目标数,那么就移动left,使两数之和整体变大;

总结:

得到的规律如下所示:

arr[left] + arr[rigth] > target:直接right--;

arr[left] + arr[rigth] < target:直接left++;

arr[left] + arr[rigth] == target:直接return;

那么以上就是本题的思路,以及图片展示,接下来就直接进行编写代码吧!!!

1.3题目代码 

1.暴力枚举

这里就是通过两层for循环实现的,具体代码如下所示:

public static int[] TwoSum(int[] arr,int target){//暴力枚举for (int i = 0; i <arr.length-1 ; i++) {for (int j = i+1; j < arr.length; j++) {if(arr[i] + arr[j]==target){return new int[]{arr[i],arr[j]};}}}return new int[]{-1};}

解释:

1.注意本题的放回的格式,是一个数组的对象;

2.这里的规定的数字之后,内层循环始终都是从外层循环的后一个开始遍历的,因为遍历过后的数字不必再次循环遍历并判断了;

时间复杂度: 由于两层for循环,那么这里的时间复杂度很明显就是O(n^2)

2.双指针

具体的代码如下所示:

 public static int[] TwoSum_Double(int[] arr,int target){//双指针算法int left=0;int right=arr.length-1;while (right>left){if (arr[right] + arr[left] > target) {right--;}else if(arr[right] + arr[left] < target){left++;}else {return new int[]{arr[left],arr[right]};}}return new int[]{-1};}

解释:

这里的代码就是通过上述的思路分析进行编写的,根据不同的情况进行操作,大于目标数直接right--,小于目标数直接left++,等于目标数直接返回这两个数,这里要注意截止的情况就是right小于left的情况;

时间复杂度:这里由于在本数组中进行操作,没有嵌套其他循环,那么时间复杂度:O(n)

📚️2.三数之和

2.1题目描述

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。得到
注意:答案中不可以包含重复的三元组。

具体的输出用例如下所示:

输入: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.2题目解析

1.暴力枚举

这里我们要注意,在判断三个数和后,由存在可能重复的情况,所以这里我们进行每个得出的数组的排序,但是这里我们可以在开始时,直接将数组进行排序,得出的可以得到两个完全相同的数组,此时我们就可以使用hashset进行去重的操作;

具体的情况就是如下的:

解释:

此时就会发现,当排序后我们的目标数组就是一样的,那么此时就可以使用hashset进行去重的操作了;

优点:容易想到,代码实现简单;

缺点:时间复杂度太高,为O(n^3),那么此时在力扣运行后肯定是超出时间限制了;

2.双指针

此时我们可以如下思路所示:

由于是要取出三个数字,那么此时规定一个数然后定义两个数,但是此时由于规定的数后,此时其余的两个数字的和肯定是这个数的相反数,那么此时就变成了:

规定一个数,其余两个数之和为这个数的相反数;

这个不就是上面求两数和为s的变种题目吗!!!

此时我们的图示就是如下所示的:

此时我们发现这不就是我们两数求和为某个数的操作吗?

第二个问题:

这里的去重也可以使用上述的hashset的方式,但是这里还有一种办法,就是每个指针找到目标的两个数后,继续移动, 这里就是一个重要的点,此时若移动后的数,和之前的数是一样的,那么此时就可以直接跳过

如下所示:

那么此时发现一样的就继续移动,知道不为一样的为止,那么就要子啊每次找到目标的两个数字后,就要进行去重的判断

注意:一个大循环规定数,这个也要进行去重的操作; 

第三个问题:

此时假如一个特殊的数组,存在后,那么这种情况下就要进行边界判断;由于每次符合前一个数等于后面一个数,(去重操作导致)就会出现越界的情况,此时也要进行判断;

2.3题目代码

小编这里只演示双指针的算法,此时大家可以试试暴力枚举的算法,当然此时放在leetcode上肯定是超时的~~~

代码如下:

public List<List<Integer>> threeSum(int[] nums) {//双指针算法,规定一个数,其他两数之和为这个数的相反数,和两数和为s的思想基本一致//规定放回的形式//先将数组进行排序的操作;Arrays.sort(nums);List<List<Integer>> ret = new ArrayList<>();for (int i = 0; i < nums.length; ) {if (nums[i] > 0) {break;}int left = i + 1;int right = nums.length - 1;int target = -nums[i];//目标相加的和的数

解释:

此时就是进行数组的重排序,然后规定放回的对象类型;

进行优化:由于确定一个数后,后面两个数和为它的相反数,若这个规定数大于0,说明后面的数更大,就不可能为它的相反数即负数;

然后规定每个指针下标;

 List<List<Integer>> ret = new ArrayList<>();for (int i = 0; i < nums.length; ) {if (nums[i] > 0) {break;}int left = i + 1;int right = nums.length - 1;int target = -nums[i];//目标相加的和的数//这里就进行目标数的相加算法while (left < right) {if (nums[left] + nums[right] > target) {right--;} else if (nums[left] + nums[right] < target) {left++;} else {ret.add(new ArrayList<>(Arrays.asList(nums[i], nums[left], nums[right])));//这里要进行去重的操作left++;right--;while (left < right && nums[left] == nums[left - 1] ) {left++;}while (left < right && nums[right] == nums[right + 1] ) {right--;}//此时可能会发生越界的问题}}

 解释:

这里就是通过上述两数和的问题的格式基本一致,但是在确定返回的数后,要进行对应的指针操作,并添加到规定的对象里;注意由于存在越界的问题,假如如下数据:

此时就会出现一直跳,跳出数组范围,所以得规定条件;

注意:

在提供条件的时候,首先得判断这里的指针的范围,不能先判断是否等于前一个数字;

这里的所谓的前一个数据:right这里前一个数据就是right++,left的前一个数据就是left--;

   i++;//解决i重复的问题while (i<nums.length && nums[i] == nums[i - 1]) {i++;}}return ret;

解释:

最后就是规定的数字必须去重,这里的去重的操作和上面的操作基本是一致的,必须是首先判断指针的的范围;然后再判断是否等于前一个数;

📚️3.总结

本期小编主要讲解了leetcode两道双指针比较重要的题目,就是“和为s的两个数”与“三数之和”;当然这里主要还是大家在看完题解后,能自己敲代码~~~

🌅🌅🌅~~~~最后希望与诸君共勉,共同进步!!!


💪💪💪以上就是本期内容了, 感兴趣的话,就关注小编吧。

                 😊😊  期待你的关注~~~

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

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

相关文章

【docker】Windows11创建Ubuntu-desktop并使用VNC完成远程访问

【docker】Windows11创建Ubuntu-desktop并使用VNC完成远程访问 文章目录 【docker】Windows11创建Ubuntu-desktop并使用VNC完成远程访问前言创建Ubuntu容器下载镜像运行容器连接容器 搭建容器XFCE桌面环境安装ubuntu桌面 总结 前言 docker ubuntu容器在深度学习领域的使用过程…

【Vulkan入门】01-列举物理设备

目录 先叨叨git信息主要逻辑VulkanEnvEnumeratePhysicalDevices()PrintPhysicalDevices() 编译并运行程序 先叨叨 上一篇已经创建了VkInstance&#xff0c;本篇我们问问VkInstance&#xff0c;在当前平台上有多少个支持Vulkan的物理设备。 git信息 repository: https://gite…

【嵌入式系统设计】LES3~5:Cortex-M4系统架构(上)第1节 ARM处理器,M4内核处理器,M4调试跟踪接口

关注作者了解更多 我的其他CSDN专栏 过程控制系统 工程测试技术 虚拟仪器技术 可编程控制器 工业现场总线 数字图像处理 智能控制 传感器技术 嵌入式系统 复变函数与积分变换 单片机原理 线性代数 大学物理 热工与工程流体力学 数字信号处理 光电融合集成电路…

微信小程序px和rpx单位互转方法

js代码如下 Page({data: {width: 0,width2: 0},onLoad: function (options) {let px this.pxToRpx(380)let rpx this.rpxToPx(730.7692307692307) // 检查两个互转是否是相同即可,例如pxToRpx(380)转成730.7692307692307 则rpxToPx(730.7692307692307)如果是380则代表互转没…

分布式推理框架 xDit

1. xDiT 简介 xDiT 是一个为大规模多 GPU 集群上的 Diffusion Transformers&#xff08;DiTs&#xff09;设计的可扩展推理引擎。它提供了一套高效的并行方法和 GPU 内核加速技术&#xff0c;以满足实时推理需求。 1.1 DiT 和 LLM DiT&#xff08;Diffusion Transformers&am…

JAVA-响应报文转XML

在我们的开发过程中&#xff0c;接口响应一般都是使用的JSON格式&#xff1b;随着我们接入的系统的增加&#xff0c;以及开发需求的增加&#xff0c;不乏出现一些使用XML解析的系统&#xff0c;需要我们将response内容转换成XML的格式响应&#xff0c;那么我们需要对此重新写个…

前端热门面试题目(三)

DIFF算法的原理 DIFF算法用于比较两棵虚拟DOM树的差异并更新真实DOM&#xff0c;其基本原理如下&#xff1a; 分层比较&#xff1a; DIFF算法假设不同层级的节点不会互相影响&#xff0c;因此只比较同一层级的节点&#xff0c;避免全树比较的高成本。 三种操作&#xff1a; D…

资料文件夹转移工具5.2.3 |快速转移到D盘,释放C盘空间

这是一款支持将C盘的常用文件夹转移到其他磁盘分区的工具&#xff0c;提供仅变目录、复制资料和转移资料三种转移方式。该工具完全免费&#xff0c;单文件免安装&#xff0c;大小仅为546KB&#xff0c;非常适合需要释放C盘空间的用户。 大小&#xff1a;546KB 下载地址&#…

xargs命令的基本语法

1. 基本语法 xargs [选项] [命令]-0, --null&#xff1a;使用null字符&#xff08;\0&#xff09;作为输入项的分隔符。这在处理包含空格、换行符等特殊字符的文件名或路径时特别有用。 -I{}&#xff1a;指定替换字符串&#xff0c;其中{}将被替换为输入行的内容。这个选项允…

学习笔记052——Spring Boot 自定义 Starter

文章目录 Spring Boot 自定义 Starter1、自定义一个要装载的项目2、创建属性读取类 ServiceProperties3、创建 Service4、创建自动配置类 AutoConfigration5、创建 spring 工程文件6、将项目打成 jar 包7、jar 打包到本地仓库8、配置application.yml Spring Boot 自定义 Starte…

windows opencv imshow图片报错解决

import cv2# 检查版本 print(cv2.__version__)# 加载一张图片&#xff08;确保你有一个名为test.jpg的文件在当前目录&#xff09; image cv2.imread(C:\\test1.jpg)# 显示图片 cv2.imshow(image, image) cv2.waitKey(0) cv2.destroyAllWindows() cv2意思是opencv c o(*&…

时间序列模型在LSTM中的特征输入

这里写目录标题 前言LSTM的输入组成时间步例子 实际代码解读特征提取处理成dataloader格式&#xff08;用于输入到模型当中&#xff09;对应到lstm的模型创建代码 总结 前言 本文章将帮助理解如何将一个时间序列的各种特征&#xff08;年月日的时间特征&#xff0c;滚动窗口滞…

uniapp 自定义导航栏增加首页按钮,仿微信小程序操作胶囊

实现效果如图 抽成组件navbar.vue&#xff0c;放入分包 <template><view class"header-nav-box":style"{height:Props.imgShow?:statusBarHeightpx,background:Props.imgShow?:Props.bgColor||#ffffff;}"><!-- 是否使用图片背景 false…

node.js基础学习-express框架-静态资源中间件express.static(十一)

前言 在 Node.js 应用中&#xff0c;静态资源是指那些不需要服务器动态处理&#xff0c;直接发送给客户端的文件。常见的静态资源包括 HTML 文件、CSS 样式表、JavaScript 脚本、图片&#xff08;如 JPEG、PNG 等&#xff09;、字体文件和音频、视频文件等。这些文件在服务器端…

下载maven 3.6.3并校验文件做md5或SHA512校验

一、下载Apache Maven 3.6.3 Apache Maven 3.6.3 官方下载链接&#xff1a; 二进制压缩包&#xff08;推荐&#xff09;: ZIP格式: https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zipTAR.GZ格式: https://archive.apache.org/dist/…

单片机知识总结(完整)

1、单片机概述 1.1. 单片机的定义与分类 定义&#xff1a; 单片机&#xff08;Microcontroller Unit&#xff0c;简称MCU&#xff09;是一种将微处理器、存储器&#xff08;包括程序存储器和数据存储器&#xff09;、输入/输出接口和其他必要的功能模块集成在单个芯片上的微型…

C# winform非常好用的图表开源控件Scottplot

wifnorm自带的chart控件功能和性能都不太行&#xff0c;所以在网上搜索到了Scottplot开源图表控件。根据自己需要&#xff0c;将已经试验使用过的用法记录在这里 winform建议使用版本 Scottplot包版本&#xff1a;4.1.71 这个版本在winform中可以以控件形式直接拖拉到窗体中使…

Python 3 教程第33篇(MySQL - mysql-connector 驱动)

Python MySQL - mysql-connector 驱动 MySQL 是最流行的关系型数据库管理系统&#xff0c;如果你不熟悉 MySQL&#xff0c;可以阅读我们的 MySQL 教程。 本章节我们为大家介绍使用 mysql-connector 来连接使用 MySQL&#xff0c; mysql-connector 是 MySQL 官方提供的驱动器。…

Gooxi Eagle Stream 2U双路通用服务器:性能强劲 灵活扩展 稳定易用

人工智能的高速发展开启了飞轮效应&#xff0c;实施数字化变革成为了企业的一道“抢答题”和“必答题”&#xff0c;而数据已成为现代企业的命脉。以HPC和AI为代表的新业务就像节节攀高的树梢&#xff0c;象征着业务创新和企业成长。但在树梢之下&#xff0c;真正让企业保持成长…

UICollectionView在xcode16编译闪退问题

使用xcode15运行工程&#xff0c;控制台会出现如下提示&#xff1a; Expected dequeued view to be returned to the collection view in preparation for display. When the collection views data source is asked to provide a view for a given index path, ensure that a …