【基础算法】——双指针算法

news2024/11/22 10:32:44

文章目录

  • 一、算法原理
  • 二、算法实战
    • 1. 力扣283 移动零
    • 2. 力扣1089 复写零
    • 3. 力扣15 三数之和
    • 4. 力扣18 四数之和
  • 三、总结


一、算法原理

双指针算法是指在遍历对象的过程中不是普通的使用单个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的。常见的双指针算法有两种:

  • 在一个序列里,用两个指针维护一段区间
  • 在两个序列里,一个指针指向一个序列,另外一个指针指向另外一个序列,来维护某种次序。

💕 算法模板

for (int i = 0, j = 0; i < n; i ++ )  // j从某一位置开始,不一定是0
{
    while (j < i && check(i, j)) j ++ ;

    // 具体问题的逻辑
}
常见问题分类:
    (1) 对于一个序列,用两个指针维护一段区间,比如快排的划分过程
    (2) 对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作

二、算法实战

1. 力扣283 移动零

在这里插入图片描述
题目链接

算法原理:

在这里插入图片描述

代码实现:

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        for(int dest = -1, cur = 0; cur < nums.size(); cur++)
            if(nums[cur])
                swap(nums[++dest], nums[cur]);
    }
};

2. 力扣1089 复写零

在这里插入图片描述
复写零

算法原理:

在这里插入图片描述

代码实现:

class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        //从前向后遍历,寻找cur和dest的位置
        int dest = -1, cur = 0, n = arr.size();
        for(cur = 0; cur < n; cur++)
        {
            if(arr[cur] == 0)
                dest+=2;
            else
                dest++;
            if(dest >= n - 1)
                break;
        }
        if(dest == n)
        {
            arr[n - 1] = 0;
            dest-=2, cur--;
        }
        while(cur >=0 && dest >= 0)
        {
            if(arr[cur] == 0)
                arr[dest--] = 0;
            arr[dest--] = arr[cur];
            cur--;
        }
    }
};

3. 力扣15 三数之和

在这里插入图片描述
三数之和

算法原理:

本题我们采用 “排序+双指针” 的思想。先将数组排序,用一层循环来枚举第一个数,当我们确定第一个元素后,另外两个元素n2+n3之和就变成了一个定值。当n2增大时n3减小,当n2减小时n3增大。

这样我们就可以在确定第一个元素后,运用双指针来同时确定第二个和第三个元素的值。当然这里我们一定要注意去重的问题,在枚举的过程中就将去重的工作顺便做了即可。

代码实现:

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        vector<vector<int>> ret;
        if(nums[0] > 0 || nums[n - 1] < 0 || n < 3)
            return ret;
        if(nums[0] == 0 && nums[n - 1] == 0)
            return {{0,0,0}};
            
        //双指针算法
        for(int i = 0; i < n - 2; i++)
        {
        	//去重
            if(i && nums[i] == nums[i - 1])
                continue;
            if(nums[i] > 0)
                break;
            int left = i + 1, right = n - 1;
            while(left < right)
            {
                int sum = nums[i] + nums[left] + nums[right];
                
                if(sum < 0)
                    left++;
                else if(sum > 0)
                    right--;
                else
                {
                    ret.push_back({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--;
                }
            }
        }
        return ret;
    }
};

4. 力扣18 四数之和

在这里插入图片描述
四数之和

算法原理:

四数之和可以在三数之和的基础上做一下修改,三数之和通过双指针解法可以将时间复杂度降到O(n2),四数之和通过双指针的方法可以将时间复杂度降到 O(n3)。具体方法为:

  • 外面双层循环,代表四个数中的前两个数。
  • 里面为一首一尾双指针,代表四个数中的后两个数,双指针逐步往中间移动,直至相遇。

代码实现:

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        vector<vector<int>> ret;

        for(int i = 0; i < n - 3; i++)
        {
            if(i && nums[i] == nums[i - 1])
                continue;
            for(int j = i + 1; j < n - 2; j++)
            {
                if(nums[j] == nums[j - 1] && j != i + 1)
                    continue;
                
                long long sum = (long long)target - nums[i] - nums[j];
                
                int left = j + 1, right = n - 1;
                while(left < right)
                {
                    if(nums[left] + nums[right] < sum)
                        left++;
                    else if(nums[left] + nums[right] > sum)
                        right--;
                    else
                    {
                        ret.push_back({nums[i], nums[j], nums[left], nums[right]});
                        left++,right--;
                        while(left < right && nums[left] == nums[left - 1])
                            left++;
                        while(left < right && nums[right] == nums[right + 1])
                            right--;
                    }
                }
            }
        }
        return ret;
    }
};

三、总结

双指针算法的用途非常的广泛,在数组和链表的操作中是非常常见的,当我们运用双指针时,需要找到目标对象的性质——单调性,当然也必须别忘了指针i和指针j的范围更新问题。最后,多刷题、多总结才能将其运用得当哦!

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

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

相关文章

机器学习实战11-基于K-means算法的文本聚类分析,生成文本聚类后的文件

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍机器学习实战11-基于K-means算法的文本聚类分析&#xff0c;生成文本聚类后的文件。文本聚类分析是NLP领域的一个核心任务&#xff0c;通过将相似的文本样本分组&#xff0c;可以帮助我们发现隐藏在文本数据中的模式和结…

Docker概述 镜像-容器基本操作

Docker 概述 Docker是一个开源的应用容器引擎&#xff0c;基于go语言开发并遵循了apache2.0协议开源。 Docker是在Linux容器里运行应用的开源工具&#xff0c;是一种轻量级的“虚拟机”。 Docker 的容器技术可以在一台主机上轻松为任何应用创建一个轻量级的、可移植的、自给自足…

Redis应用(7)——Redis的项目应用(六):布隆过滤器---白名单 ----> Reids的问题,雪崩/ 击穿 / 穿透【重要】 布隆过滤器

目录 引出Redis的问题缓存雪崩&#xff1a;key不存在缓存击穿&#xff1a;热点key缓存穿透【重要】 穿透的解决方案&#xff1a;布隆过滤器问题&#xff1a;如何存储100w纯数字布隆过滤器项目应用&#xff1a;布隆过滤器≈白名单htool工具包案例 Redis项目应用&#xff08;六&a…

OpenCV4图像处理-图像交互式分割-GrabCut

本文将实现一个与人&#xff08;鼠标&#xff09;交互从而分割背景的程序。 GrabCut 1.理论介绍2. 鼠标交互3. GrabCut 1.理论介绍 用户指定前景的大体区域&#xff0c;剩下为背景区域&#xff0c;还可以明确指出某些地方为前景或者背景&#xff0c;GrabCut算法采用分段迭代的…

蓝桥杯专题-真题版含答案-【星系炸弹】【隔行变色】【手链样式】【生日蜡烛】

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

Python爬虫-进入浏览器控制台就出现无限debugger,怎么解决?

前言 本文是该专栏的第53篇,后面会持续分享python爬虫干货知识,记得关注。 对于控制台出现无限debugger的情况,笔者之前在“JS逆向-常见反调试之“无限Debugger”,怎么解决?”里面有详细介绍过。而本文,针对控制台调试出现无限debugger的另一种情况,笔者来详细介绍该问…

C语言的自定义类型(结构体、枚举、联合体)

“虽然前方拥堵&#xff0c;但您仍在最优路线上” ——高德地图 文章目录 一、结构体类型 1.结构体类型的定义 2.结构体变量的初始化 3.结构体类型变量的定义 4.结构体内存对齐 5.结构体实现位段 二、枚举类型 三、联合体类型 大家好&#xff0c;我是纪宁。 这篇文章主…

【数据结构】--八大排序算法【完整版】

匠心制作&#xff0c;后续有问题会加以修改的 &#xff0c;全文均是自己写的&#xff0c;几张图有参考网络 ———————————————— 目录 一、直接插入排序 二、希尔排序(直接插入排序的改良版) 三、选择排序&#xff08;直接选择排序&#xff09; 四、堆排序 …

通过YOLOV5实现:王者荣耀百里守约自瞄

前期提要&#xff1a; 本文章仅供技术讨论使用。 关于如何通过YOLOV5去检测到王者中的敌方人物&#xff0c;在网上有很多相关的文章和教学视频我在这里就不过多的阐述&#xff0c;本篇文章主要讲的是在实现中比较难处理的一些技术点&#xff1a;如何获取高刷新率的手机屏幕、…

Hive 调优集锦(1)

一、前言 1.1 概念 Hive 依赖于 HDFS 存储数据&#xff0c;Hive 将 HQL 转换成 MapReduce 执行&#xff0c;所以说 Hive 是基于Hadoop 的一个数据仓库工具&#xff0c;实质就是一款基于 HDFS 的 MapReduce 计算框架&#xff0c;对存储在HDFS 中的数据进行分析和管理。 1.2 架…

贤鱼的刷题日常(数据结构链表学习)-1748:约瑟夫问题--题目详解

&#x1f3c6;今日学习目标&#xff1a; &#x1f340;例题讲解1748:约瑟夫问题 ✅创作者&#xff1a;贤鱼 ⏰预计时间&#xff1a;15分钟 &#x1f389;个人主页&#xff1a;贤鱼的个人主页 &#x1f525;专栏系列&#xff1a;c &#x1f341;贤鱼的个人社区&#xff0c;欢迎你…

NLP实战8:图解 Transformer笔记

目录 1.Transformer宏观结构 2.Transformer结构细节 2.1输入 2.2编码部分 2.3解码部分 2.4多头注意力机制 2.5线性层和softmax 2.6 损失函数 3.参考代码 &#x1f368; 本文为[&#x1f517;365天深度学习训练营]内部限免文章&#xff08;版权归 *K同学啊* 所有&#…

Okhttp-LoggingInterceptor的简单使用

概述 Okhttp除了提供强大的get,post网络请求外&#xff0c;还包含请求日志的拦截器&#xff0c;可以监视&#xff0c;重写&#xff0c;重试调用请求。 简单使用 我们在构造OkHttpClient时&#xff0c;通过addInterceptor()方法添加我们需要的过滤器。 object OkhttpUtils{……

SpringBoot知识范围-学习步骤【JSB系列之000】

语言视频选择收录专辑链接C张雪峰推荐选择了计算机专业之后-在大学期间卷起来-【大学生活篇】JAVA黑马B站视频JAVA部分的知识范围、学习步骤详解JAVAWEB黑马B站视频JAVAWEB部分的知识范围、学习步骤详解SpringBootSpringBoot知识范围-学习步骤【JSB系列之000】微信小程序详细解…

【stable diffusion】保姆级入门课程04-Stable diffusion(SD)图生图-局部重绘的用法

目录 0.本章素材 1.什么是局部重绘 2.局部重绘和涂鸦有什么不同 3.操作界面讲解 3.1.蒙版模糊 3.2.蒙版模式 3.3.蒙版蒙住的内容 3.4.重绘区域 4.局部重绘的应用&#xff08;面部修复&#xff09; 5.课后训练 0.本章素材 chilloutmix模型(真人模型)百度地址&#xf…

数据结构—树状数组

树状数组 单点修改、区间查询区间修改、单点查询区间修改、区间查询 单点修改、区间查询 这里讲解树状数组的最基本操作单点修改、区间查询&#xff0c;当然能做到单点修改、区间查询&#xff0c;肯定就能做到单点修改、单点查询了。树状数组是用来快速求前缀和的&#xff0c;…

MGRE之OSPF实验

目录 题目&#xff1a; 步骤二&#xff1a;拓扑设计与地址规划​编辑 步骤三&#xff1a;IP地址配置 步骤四&#xff1a;缺省路由配置 步骤五&#xff1a;NAT的配置 步骤六&#xff1a;MGRE配置 中心站点R1配置 分支站点配置 中心站点R5 R1配置 分支站点配置 检测&…

UE 材质学习补充

Add Name Reroute Node ...&#xff08;本地变量&#xff09; 该节点可以整理节点&#xff0c;优化界面 Texture Texture(纹理图像)&#xff0c;一般由RGB三个通道混合构成&#xff0c;RGB三个通道的值代表亮度&#xff0c;RGB三个通道分别都是0-1&#xff08;0-255&#xff09…

征服FarmerJohn(二) Naptime【USACO05JAN】

题解目录 前言题目内容题目描述输入输出样例题目思路示例代码AC图片 后记往期精彩 前言 在上一期征服FarmerJohn&#xff08;一&#xff09;三角形【USACO2020FEB-B】结束之后&#xff0c;我们来看一道难度有所提升的DP问题&#xff0c;也就是常说的动态规划&#xff0c;今天我…

Please set the ROCKETMQ_HOME variable in your environment!

原因 启动ROCKETMQ执行命令start mqnamesrv.cmd时报错 翻译意思是请在您的环境中设置ROCKETMQ_HOME变量&#xff01; 查看mqnamesrv.cmd可以看到如果"%ROCKETMQ_HOME%\bin\runserver.cmd"不存在会报此错误 配置上环境变量ROCKETMQ_HOME即可