双指针算法

文章目录

  • 双指针算法
  • leetcode题目


双指针算法

双指针算法可以实现对于时间复杂度降一维度,使得O(n2)的算法时间复杂度变为O(n)

指针类型

  1. 对撞指针
  2. 快慢指针

对撞指针

  • 一般是用于顺序结构中的,也可以称为左右指针,从两端向中间移动,最左、最右,向中间逐渐逼近。
  • 对撞指针的结束条件一般为left==right 或者 left>right

快慢指针

  • 基本思想为使用两个移动速度不同的指针在数组或者链表等序列结构上移动,比如在处理环形链表或者是数组时很有用
  • 只要是我们研究的问题涉及到循环往复的情况,就可以考虑使用快慢指针的思想
  • 快慢指针的实现方式有很多种,但是最为经典的是,在一次循环中,每一次让慢的指针移动一步,快的指针移动两步,如果成环(循环),那么两个指针会相遇

leetcode题目

题目链接:移动零
在这里插入图片描述

class Solution {
public:void moveZeroes(vector<int>& nums) {    //这是数组划分的题目,我们使用双指针的方式来解决//cur=0 dest=-1 dest指向的是最后一个不为0的数//移动cur,查找是否有nums[cur]!=0 那么 与nums[++dest] 交换,使得//[0,dest]  [dest+1,cur-1]  [cur,n-1]//数组分为上述三部分,第一部分为非零部分   第二部分为0部分,第三部分为未处理的部分//我们将非零部分,找到之后就放在当前非零数组的最后一个元素之后的位置,这样就可以实现分块for(int cur=0,dest=-1;cur<nums.size();cur++){if(nums[cur]){//如果不为0swap(nums[++dest],nums[cur]);}}}
};

为什么是swap(nums[++dest],nums[cur]),这是因为我们规定的是dest位置是已处理区域的最后一个非零元素,我们发现在未处理区域cur之后,发现非零元素,将++dest,得到最后一个元素的后一个位置,进行交换,自然实现了0(已处理的零区域)与nums[cur]的移动

题目描述:复写零

在这里插入图片描述

class Solution {
public:void duplicateZeros(vector<int>& arr) {//对于数组的元素进行处理,我们使用双指针//因为复写,遇到0要复写0,所以从前向后的双指针不行,我们使用从后向前指针,这样就不会造成数据被覆盖//从后向前进行双指针,我们首先要确定的是开始判断是否复写的起始位置//起始位置的确定,就是复写完毕之后的数组最后一个元素在原先数组中的下标位置//我们使用双指针进行判断,找到确定的位置//先找到最后一个位置//找到位置之后,可能会有种可能nums[dest]=0 所以我们将这种可能避免int cur=0,dest=-1;   //cur比dest多1,实际上就是先++cur,然后进行判断while(cur<arr.size()){if(arr[cur]){dest++;}else{dest+=2;}if(dest>=arr.size()-1){break;}cur++;}cout<<arr[cur]<<endl;//处理边界问题,dest可能大于arr.size()-1if(dest==arr.size()){arr[arr.size()-1] =0;dest-=2;cur--;}//开始复写 ,从后向前while(cur>=0){if(arr[cur]){//如果不为0arr[dest]=arr[cur];cur--;dest--;}else{//为0 复写arr[dest]=arr[cur];arr[--dest]=arr[cur];--dest;--cur;}}}
};

题目描述:快乐数

在这里插入图片描述

class Solution {
public://得到每一位数字的平方和int func(int n){int ans=0;while(n){ans+=(n%10)*(n%10);n=n/10;}return ans;}bool isHappy(int n) {//根据题意所知,不管如何都会形成一个循环//根据循环,我们知道之前判断循环链表的做法,快慢指针的形式//slow和fast都是指向经过平方之后的数字,来代替指针 //slow走一步平方一次,fast平方两次//实现平方的函数cout<<func(100)<<endl;//检验func函数int slow=n;int fast=n;while(1){//直到相等才停止slow=func(slow);fast=func(fast);fast=func(fast);if(slow==fast){break;}}if(slow==1){return true;}else{return false;}//return true;}
};

题目描述:盛最多水的容器

在这里插入图片描述

class Solution {
public:int maxArea(vector<int>& height) {//使用双指针的算法来解决//在两边设置指针,移动较小的哪一方指针,然后计算此时的体积,不断的移动,直到相遇int left=0,right=height.size()-1,ans=0;while(left<right){//先得到此时的体积int v=(right-left)*min(height[left],height[right]);ans=max(v,ans);if(height[right]>height[left]){left++;}else{right--;}}return ans;}
}

题目描述:有效三角形的个数

在这里插入图片描述

class Solution {
public:int triangleNumber(vector<int>& nums) {sort(nums.begin(),nums.end());int ans=0;for(int i=nums.size()-1;i;i--){int target=nums[i];int left=0,right=i-1;while(left<right){if(nums[left]+nums[right]>target){//满足三角形ans+=right-left;right--;//left++;}else{left++;}}}return ans;}
};

利用数组元素的单调性,先确定一个元素,然后使用双指针,判断当前三者是否符合三角形,如果符合,根据单调性,left左边的所有都符合,所以ans+=right-left,然后向左移动right,如果不符合,那么向右移动left,一直判断,一直ans+=right-left 直到left<right 更换下一位c,最后循环操作,返回ans

题目描述:和为s的两个数字

在这里插入图片描述

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {//因为是 递增的数组   //我们利用双指针算法来解决该问题   利用单调性进行优化vector<int> v;int left=0,right=nums.size()-1;while(left<right){if(nums[left]+nums[right]<target){left++;  //说明当前最大值加上最小值还是小于target}else if(nums[left]+nums[right]== target){v.push_back(nums[left]);v.push_back(nums[right]);return v;}else{right--;}}return v;}
};

题目概述:三数之和

在这里插入图片描述

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {sort(nums.begin(),nums.end());//进行排序,然使用双指针算法,先确定一个数字,然后移动另外两个指针进行加减vector<vector<int>> vv;for(int i=0;i<nums.size();){if(nums[i]>0) break;int left=i+1,right=nums.size()-1;while(left<right){int sum=nums[left]+nums[right];int target=-nums[i];if(sum==target){vector<int> v;v.push_back(nums[i]);v.push_back(nums[left]);v.push_back(nums[right]);//找到一次之后,对于相邻重复的元素进行跨越vv.push_back(v);//去重操作 left 和 rightleft++,right--;while(left<right && nums[left] == nums[left-1]) left++;while(left<right && nums[right] == nums[right+1]) right--;//防止越界}else if(sum>target){right--;}else {left++;}}//去重操作 ii++;while(i<nums.size() && nums[i] == nums[i-1]) i++;}return vv;}
};

题目描述:四数之和

在这里插入图片描述

class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {//先固定一个数a,然后剩余三个数字用三数之和 的内容来解决sort(nums.begin(),nums.end());vector<vector<int>> vv;for(int i=0;i<nums.size();){int a=nums[i];for(int j=i+1;j<nums.size();){//三数之和的内容int num=target-a;int left=j+1,right=nums.size()-1;while(left<right){int sum=nums[left]+nums[right];long t=(long)num-nums[j];if(sum>t){right--;}else if(sum<t){left++;} else{vv.push_back({nums[i],nums[j],nums[left],nums[right]});//加入vector后,处理重复问题 left 和 rightleft++, right--;while(left<right && nums[left] ==  nums[left-1]) left++;while(left<right && nums[right] ==  nums[right+1]) right--;}}//去重处理 jj++;while(j<nums.size() && nums[j] == nums[j-1]) j++;}i++;while(i<nums.size() && nums[i] == nums[i-1]) i++; }return vv;}
};

总结:
双指针的使用场景有很多种,使用对撞指针还是快慢指针是根据题意分析的,如果成环我们就使用快慢指针,双指针的算法是根据暴力算法的优化得到的,通过省去不必要的迭代,来实现优化。

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

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

相关文章

【工作中问题解决实践 十一】Kafka消费者消费堆积且频繁rebalance

最近有点不走运&#xff0c;老是遇到基础服务的问题&#xff0c;还是记着点儿解决方法&#xff0c;以后再遇到快速解决吧&#xff0c;今天遇到这个问题倒不算紧急&#xff0c;但也能通过这个问题熟悉一下Kafka的配置。 问题背景 正在开会的时候突然收到一连串的报警&#xff…

上篇文章viewerjs(npm包补丁)的错误更正。(npm补丁本地没问题,流水线打包要没效果,要么报错)

1、上篇文档的包补丁在本地使用没有问题&#xff0c;并且同事拉代码后也会自动同步npm_modules&#xff0c;也没有问题 2、问题出现在打包上&#xff0c;我这边的项目是用teambition上的飞流设置的流水线来进行打包的&#xff0c;里面用到了两个指令 yarn install npm run bu…

IDEA关闭项目,但是后台程序没有关闭进程(解决方案)

最近遇到一个很奇怪的问题&#xff0c;idea关闭项目后&#xff0c;系统进程没有杀死进程&#xff0c;再次执行的时候会提示端口占用&#xff0c;并提示Process exited with an error: 1 (Exit value: 1) 错误原因&#xff1a;应用程序关闭后&#xff0c;进程不能同步关闭 解决方…

使用ffmpeg将m4a及wav等文件转换为MP3格式

要使用ffmpeg将m4a及wav等文件转换为MP3格式&#xff0c;您可以按照以下步骤进行操作&#xff1a; 安装 ffmpeg 确保您已经安装了ffmpeg软件。如果没有安装&#xff0c;请访问ffmpeg的官方网站https://ffmpeg.org/ 并按照说明进行安装。 Win10 / Win11 可以通过 winget 命令…

角角の Qt学习笔记(一)

目录 一、解决在创建新项目时遇到的几个问题 二、信号和槽&#xff08;非自定义&#xff09; 三、调用 UI 中的元素&#xff08;比如按钮&#xff09; 一、解决在创建新项目时遇到的几个问题 在新建项目时&#xff0c;我选择的构建系统为CMake。然后勾选了Generate form&…

fabric.js里toDataURL后,画布内容展示不全?

复现场景&#xff1a; 用fabric生成画布后&#xff0c;转成图片&#xff0c;然后直接在浏览器里打开&#xff0c;画布展示内容缺失 画布原图&#xff1a; toDataURL后链接在浏览器打开&#xff1a; 原因解析&#xff1a; base64链接太长&#xff0c;输入浏览器链接被截断&…

MySQL 数据库文件的导入导出

目录 数据库的导出 导出整个数据库 导出数据库中的数据表 导出数据库结构 导出数据库中表的表结构 导出多个数据库 导出所有数据库 数据库的导入 数据库的导出 mysqldump -h IP地址 -P 端口 -u 用户名 -p 数据库名 > 导出的文件名 用管理员权限打开cmd进入MySQL的bi…

python+tkinter实现图书管理系统(首发)

文章目录 前文运行环境功能图数据操作图书数据管理用户数据管理借书记录管理 功能界面管理员界面首页图书管理用户管理借书记录更改密码 普通用户界面 其他功能数字时间显示加载画面显示输入框提示词界面居中显示借书时间和还书时间记录公告栏数据操作 结尾 前文 本文将用tkin…

springboot异步任务

在Service类声明一个注解Async作为异步方法的标识 package com.qf.sping09test.service;import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service;Service public class AsyncService {//告诉spring这是一个异步的方法Asyncp…

JavaWeb 中对 HTTP 协议的学习

HTTP1 Web概述1.1 Web和JavaWeb的概念1.2 JavaWeb技术栈1.2.1 B/S架构1.2.2 静态资源1.2.3 动态资源1.2.4 数据库1.2.5 HTTP协议1.2.6 Web服务器 1.3 Web核心 2 HTTP2.1 简介2.2 请求数据格式2.2.1 格式介绍2.2.2 实例演示 2.3 响应数据格式2.3.1 格式介绍2.3.2 响应状态码2.3.…

面试热题(合并两个有序列表)

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 合并链表这类型题也是比较经典的题了&#xff0c;因为链表是由指针相互指向而确定位置&#xff0c;所以我们只需要改变某些节点的指针便可以做到对链表进行排序 今天这个方法…

Java课题笔记~ 会话跟踪

3.1 Cookie 【案例1 记住密码】 实现效果 当勾选“记住密码”复选框时&#xff0c;下次访问登录页面&#xff0c;会自动记住账号&#xff0c;密码信息。 【案例2 上次访问时间】 实现效果 首次登录&#xff0c;显示“欢迎您&#xff0c;XXX” 下次登录&#xff0c;显示“欢迎您…

Spring Bean 生命周期的执行流程

问题描述 Spring 生命周期全过程大致分为五个阶段&#xff1a; 1、创建前准备阶段 2、创建实例阶段 3、依赖注入阶段 4、 容器缓存阶段 5、销毁实例阶段 下图是 Spring Bean 生命周期完整流程图&#xff0c;其中对每个阶段的具体操作做了详细介绍&#xff1a; 一、创建前准备阶…

java 把list转成json

在Java中&#xff0c;将List转换成JSON格式是非常常见的任务。JSON是一种轻巧的数据交换格式&#xff0c;非常适合于Web应用程序&#xff0c;特别是前端开发。 使用Java将List转换成JSON格式的最简单方法是通过JSON库。最常用的JSON库是 Jackson&#xff0c;它提供了快速&…

阶梯费用计算(配置化_最小demo)

本文旨在提供一种配置化思路计算阶梯费用&#xff0c;更高级的做法则是通过数据库配置&#xff0c;注册中心等&#xff1b;在表达式上可以采用自定义或者spel表达式等其他方式进行处理&#xff1b;(代码仅展示最小demo,部分不完善地方自行补充) 思路&#xff1a;N个区间对应N个…

Spring Boot 项目应用消息服务器RabbitMQ(简单介绍)

一、背景 本章讲述的是在用户下单环节&#xff0c;消息服务器RabbitMQ 的应用 1.1 消息服务器的应用 在写一个电商项目的小demo&#xff0c;在电商项目中&#xff0c;消息服务器的应用&#xff1a; 1、订单状态通知&#xff1a;当用户下单、支付成功、订单发货、订单完成等…

【MFC】10.MFC六大机制:RTTI(运行时类型识别),动态创建机制,窗口切分,子类化-笔记

运行时类信息&#xff08;RTTI&#xff09; C: ##是拼接 #是替换成字符串 // RTTI.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include <iostream> #include <afxwin.h>#ifdef _DEBUG #define new DEBUG_NEW #endifCWinApp th…

六种不同的CRM系统类型分别有哪些特点?

企业想要管理销售&#xff0c;可以选择CRM系统&#xff1b;企业想要优化业务流程&#xff0c;可以选择CRM系统&#xff1b;企业想要提高收入&#xff0c;可以选择CRM系统。下面来说说&#xff0c;CRM是什么&#xff1f;六种常见CRM系统类型对比。 什么是CRM&#xff1f; CRM是…

优秀的 Modbus 从站(从机、服务端)仿真器、串口调试工具

文章目录 优秀的 Modbus 从站&#xff08;从机、服务端&#xff09;仿真器、串口调试工具主要功能软件截图 优秀的 Modbus 从站&#xff08;从机、服务端&#xff09;仿真器、串口调试工具 官网下载地址&#xff1a;http://www.redisant.cn/mse 主要功能 支持多种Modbus协议…

Java课题笔记~ Spring 集成 MyBatis

Spring 集成 MyBatis 将 MyBatis 与 Spring 进行整合&#xff0c;主要解决的问题就是将 SqlSessionFactory 对象交由 Spring 来管理。所以该整合&#xff0c;只需要将 SqlSessionFactory 的对象生成器SqlSessionFactoryBean 注册在 Spring 容器中&#xff0c;再将其注入给 Dao…