双指针--优选算法

news2024/11/15 17:31:39

个人主页:敲上瘾-CSDN博客

个人专栏:游戏、数据结构、c语言基础、c++学习、OJ题

前言:

        该篇文章我们主要来学习的是双指针算法,对于该类算法我们可以直接来做题,从题中去感知该算法的魅力,最后再从题中做总结。接下来我准备了3道题,每道题会分为三个步骤讲解,分别是题目解析、算法原理、代码编写去讲解,最后再做总结。

目录

一、移动零

1.题目解析

2.算法原理

3.代码编写

二、盛水最多的容器

1.题目解析

2.算法原理

(1)、解法一(暴力枚举):

(2)、解法二(利用单调性):

3.代码编写

三、快乐数

1.题目解析

2.算法原理

3.代码编写

四、总结


一、移动零

1.题目解析

        该题的题目要求把数组中的零全部移到右边,并且保持非零元素的相对位置不变,这里举例了个例子[ 0,1,0,3,12],移动后[1,3,12,0,0],原本非零元素的数据顺序是1在前2其次最后是12,修改后的数据同样保持1在前2其次最后是12的顺序,只是把零元素移动到最后面。

2.算法原理

        在我们在讲算法原理的时候要注意一个前提条件:不复制数组

        该题我在这里把它归类为数组划分的类型,也就是给定一个规则,然后依这个规则把数组里的元素划分出不同的区间,如:此问题可以理解为把混乱的数据划分为零区间与非零区间,区间与区间之间可以用指针把它们分开。

注意这里说的指针并不是真的指针,而是数组的下标,双指针只是一种思想。

        一个指针可以分两个区间,但是刚开始元素是混乱的,并不能一次性把它处理完,所以还需要一个区间来存放待处理的元素,那么就需要用两个指针来把区间分开,如下:

        这里可以让p1指向非零区间的最后一个元素,p2指向待处理区间的第一个元素,这样的话如果p2遍历到非零元素的话就可以直接与++p1后交换元素。而如果p2遍历到零元素的话并不需要做任何改动,p2继续遍历。那么随着p2遍历结束整数组就只剩下非零区间和零区间,而且非零元素的相对顺序依旧不变。这样这个算法就算完成了

3.代码编写

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

涉及用双指针划分数组的还有快速排序的核心部分,如下:

二、盛水最多的容器

1.题目解析

        该题目的意思是给一个数组,数组的下标代表柱子的横坐标,下标对应的元素代表着高度,选择两个柱子,两坐标相差的值作为容器长度,而选纵坐标最小的作为容器高度。然后构成一个容器,宽乘以高表示容器的储水量,如下:下标3和7的柱子的储水量。

2.算法原理

(1)、解法一(暴力枚举):

        该题最容易想到也是最容易理解的应该就是暴力枚举了,直接用两层循环一一枚举并更新容器最大容量。时间复杂度为O(N^2),效率比较低在这里就不再多讲我们直接来看解法二。

(2)、解法二(利用单调性):

        因为坐标是从左往右单调增的,所以首先选定围成宽度最宽的两个柱子,然后记录它们容器容量,如下图所示:

        现在围成的容量并不一定是最大的,但通过观察很容易发现如果我们把right往左挪动容器容量必然会减小,因为right往左挪动后宽度是必然会减小的,而根据题目要求高度只能取较小那个,即取的高度小于等于1。所以我们可以根据这个性质减少不必要的枚举,只让指向较小的那个元素1的left往右移,然后记录容量。

        通过以上发现的性质我们就可以设计算法了,首先用left指针指向0下标,right指针指向最后一个元素的下标,然后计算并更新最大容量。如果left指向元素较小那么left右移,如果right指向元素较小那么right左移,然后计算并更新最大容量。循环进行直到left与right相遇,最后返回最大容量。

3.代码编写

class Solution {
public:
    int maxArea(vector<int>& height) {
        int sum=0,left=0,right=height.size()-1;
        while(left!=right)
        {
            sum=max(sum,(right-left)*min(height[left],height[right]));
            if(height[left]<height[right]) left++;
            else right--;
        }
        return sum;
    }
};

三、快乐数

1.题目解析

        该题目的意思是给定一个数然后把它的各个位数平方相加生成一个新的数,然后再次对这个新的数的各个位数的平方相加生成新的数,循环往复操作直到这个数变成1返回true或者根本变不到1返回false。如上19,它的个位数的平方加十位数的平方得到新的数82,继续对82进行同样的操作直到能够判断它是否能变为1。

2.算法原理

        该题的重难点就在于如何判断该数能不能变为1,在题目中有一个要点:重复该操作可能使这个数变为1,也可能进入无限循环。而这个数变到1后继续操作也是无限的循环

出现循环我们就很容易想到用快慢指针处理追击问题,这个思想这里也同样适用,把每次操作当做指针移动。

        把两个指针放入循环内,单趟循环内快指针fast操作两次,慢指针slow操作一次,那么当数据进入循环后,fast必然会与slow相遇(即数据相等),如果此位置为1那么这个数就能变成1返回true,如果不是则不能变成1返回false。

3.代码编写

class Solution {
public:
    int _isHappy(int m)
    {
        int sum=0;
        while(m)
        {
            sum+=(m%10)*(m%10);
            m/=10;
        }
        return sum;
    }
    bool isHappy(int n) {
        int fast=n,slow=n;
        do
        {
            fast=_isHappy(fast);
            slow=_isHappy(_isHappy(slow));
        }while(fast!=slow);
        return fast==1;
    }
};

四、总结

        1、以上三道题分别对应数组划分、数据的单调性、数据的循环,在以后涉及这种类型题的时候都可以从双指针方向去考虑。

        2、对于能使用暴力枚举解决的问题也可以考虑使用双指针去降低时间复杂度提高效率。

        3、通常所说的双指针算法只是一种思想并不是用真的使用指针。

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

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

相关文章

【数据结构】—— 线性表

目录 前言一、顺序表1.1 顺序表的定义及其特点1.2 顺序表的C语言实现1.2.1 定义顺序表1.2.2 初始化1.2.3 插入1.2.4 删除1.2.5 查找 二、链表2.1 链表的定义2.2 单向链表的实现2.2.1 定义单向链表2.2.2 创建链表2.2.3 插入元素2.2.4 删除元素2.2.5 查找 2.3 双向循环链表 前言 …

选刊风向标!985大学近十年发文热门IEEE期刊盘点

本期盘点同济大学近十年有关IEEE旗下发文较多的期刊&#xff0c;一起来看看哪些是双一流大学热门发文期刊&#xff1a; 1、IEEE Transactions on Cybernetics • 影响因子&#xff1a;9.4 • JCR1区&#xff0c;中科院1区-Top • 检索数据库&#xff1a;SCIE • 期刊分区&a…

stable diffusion的安装

stable diffusion的安装 一、前言二、安装python环境1、已经安装python环境&#xff0c;但非3.10.6版本&#xff08;可以不看&#xff09; 三、安装stable diffusion四、运行五、启动报错1、Torch is not able to use GPU2、Installing open_clip 卡住3、报错提示 "git&qu…

systemverilog中的DPI-C用例介绍

文章目录 前言一、dpi_longint二、dpi_packed_array三、dpi_structure四、相关参考总结 前言 本文主要基于VCS内置的三个关于DPI-C的使用用例&#xff0c;记录一下DPI-C的使用方法。测试用例的路径为$VCS_HOME/doc/examples/testbench/sv/。测试用例包括&#xff1a;dpi_longi…

自然语言处理:第四十三章 视觉RAG:变革传统深度学习模型开发流程,开创下一代多模态视觉模型的新时代

文章链接:微信公众平台 (qq.com) 写在前面: 笔者更新不易&#xff0c;希望走过路过点个关注和赞&#xff0c;笔芯!!! 写在前面: 笔者更新不易&#xff0c;希望走过路过点个关注和赞&#xff0c;笔芯!!! 写在前面: 笔者更新不易&#xff0c;希望走过路过点个关注和赞&#xff…

Chaper 09 深入理解Promise

文章目录 前言一、异步编程二、Promise 前言 在JavaScript中&#xff0c;异步编程是一个重要的概念。随着应用程序的复杂性增加&#xff0c;处理异步操作的方式也变得更加复杂。Promise是一种用于处理异步操作的对象&#xff0c;它提供了一种更清晰和更强大的方式来管理异步代…

智能的JavaScript开发工具WebStorm v2024.2全新发布

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具&#xff0c;被广大中国JS开发者誉为"Web前端开发神器""强大的HTML5编辑器""智能的JavaSscript IDE"等。与IntelliJ IDEA同源&#xff0c;继承了IntelliJ IDEA强大的JS部分的功能。 立即获…

学生防近视台灯什么品牌好?学生护眼台灯怎么选?收下这份攻略

根据中国报告大厅的数据&#xff0c;近年来&#xff0c;随着科技的不断进步&#xff0c;台灯行业亦得到了快速发展。早期的台灯主要采用白炽灯作为光源&#xff0c;但随着LED技术的日益成熟&#xff0c;LED台灯已成为市场主流。目前&#xff0c;台灯行业正处于高速发展阶段&…

【吊打面试官系列-Redis面试题】Redis 过期键的删除策略?

大家好&#xff0c;我是锋哥。今天分享关于 【Redis 过期键的删除策略】面试题&#xff0c;希望对大家有帮助&#xff1b; Redis 过期键的删除策略&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 1、定时删除:在设置键的过期时间的同时&#xff0c;创建…

19 - 路径搜索的综合

---- 整理自狄泰软件唐佐林老师课程 文章目录 1. 需求2. 一些工具3. 编译规则的依赖4. 实验 1. 需求 工程项目中不希望源码文件夹在编译时被改动&#xff08;只读文件夹&#xff09;在编译时自动创建文件夹&#xff08;build&#xff09;用于存放编译结果编译过程中能够自动搜…

java基本程序设计结构与数据类型

1.一个简单程序的编写、编译与运行 编写如下的Main.java public class Main{public static void main(String[] args){System.out.println("Hello World");} }上面的程序有几个要注意的点&#xff1a; ①public 是访问修饰符&#xff0c;用来表示其他程序对Main类的…

【C++】vector(下)--下篇

个人主页~ vector&#xff08;上&#xff09;~ vector&#xff08;下&#xff09;–上篇~ vector 二、模拟实现3、test.cpptest1test2test3test4test5test6 三、一个难题 二、模拟实现 3、test.cpp test1 这个没啥好说的&#xff0c;就是尾插和迭代器都能正常使用 //测尾…

中国各、省、市、县、乡镇基尼系数数据(2000-2023年)

基尼系数是一个国际上广泛用来综合考察居民内部收入分配差异状况的重要指标。它表示在全部居民收入中&#xff0c;用于进行不平均分配的那部分收入占总收入的百分比。基尼系数的值介于0和1之间&#xff0c;其中0代表收入分配绝对平均&#xff0c;即每个人的收入都相等&#xff…

Qt21基础图形的绘制

基础图形的绘制 paintareapaintarea.hpaintarea.cpp paintexpaintex.hpaintex.cpp main.cpp运行图 paintarea paintarea.h #ifndef PAINTAREA_H #define PAINTAREA_H#include <QWidget> #include <QBrush> #include <QPen> #include <QPainter> #inc…

DZ主题模板 Discuz迪恩淘宝客购物风格商业版模板

Discuz淘宝客网站模板&#xff0c;迪恩淘宝客购物风格商业版模板。 版本支持&#xff1a;discuzx3.0版本,discuzx3.1版本,discuzx3.2版本。 包括网站首页&#xff0c;论坛首页&#xff0c;论坛列表页&#xff0c;论坛内容页&#xff0c;论坛瀑布流,频道列表页&#xff0c;频道…

开学季好物合集有哪些?全方位必备好物推荐

随着秋风轻拂&#xff0c;书页翻新的声音在耳边悄然响起&#xff0c;我们迎来了又一个开学季。在这个特别的时刻&#xff0c;每位学子都怀揣着对未来的无限憧憬&#xff0c;踏入了校园的大门。为了帮助大家更好地适应新学期的学习节奏&#xff0c;享受更加充实而愉快的校园生活…

解决Linux安装epel源提示没有可用安装包

目录 前言 常规方法总结 1、命令直接安装 2、通过网址下载安装 手动安装 1、EPEL的资源地址 2、选择版本 3、找到rpm文件存放位置 4、下载并移动至虚拟机中 5、安装 6、成功后会生成相应的repo文件 7、更新源 前言 EPEL&#xff0c; 即Extra Packages for Enterpri…

STM32开发资料

文章目录 前言一、正点原子&#xff1f;1. 资料链接2.论坛3.参考资料盘 二、野火1. 论坛2. 资料链接 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 学习需要&#xff1a;找一个开发板的资料作为基础 提示&#xff1a;以下是本篇文章正文内容&…

Redis 键值对操作全攻略

文章目录 一 . get 和 set二 . keys *三 . exists四 . del五 . expire六 . ttl七 . Redis 的 key 的过期策略八 . 定时器的实现8.1 基于优先级队列8.2 基于时间轮实现的定时器 九 . type十 . 数据库管理相关命令 Hello , 大家好 , 这个专栏给大家带来的是 Redis 系列 ! 本篇文章…

聊聊客户端/服务器与订阅/发布两大模型

正文 大家好&#xff0c;我是bug菌&#xff5e; 在项目开发中根据不同的应用场景通常会去尝试各种各样的通信方式&#xff0c;可能试来试去可能又回到了原地&#xff0c;而对于一个相对比较大的网络系统&#xff0c;不同的场景得考量不同的通信架构模型&#xff0c;那么今天就跟…