【算法笔记】双指针算法深度剖析

news2024/11/28 10:48:20

【算法笔记】双指针算法深度剖析

🔥个人主页大白的编程日记

🔥专栏算法笔记


文章目录

  • 【算法笔记】双指针算法深度剖析
    • 前言
      • 一.移动零
      • 1.1题目
      • 1.2思路分析
      • 1.3代码实现
      • 二.复写零
      • 2.1题目
      • 2.2思路分析
      • 2.3代码实现
    • 三.快乐数
      • 3.1题目
      • 3.2思路分析
      • 3.3代码实现
    • 四.盛水最多的容器
      • 4.1题目
      • 4.2思路分析
      • 4.3正确性证明
      • 4.4代码实现
    • 五.有效三角形个数
      • 5.1题目
      • 5.2思路分析
      • 5.3代码实现
    • 六.两数之和
      • 6.1题目
      • 6.2思路分析
      • 6.3代码实现
    • 七.三数之和
      • 7.1题目
      • 7.2思路分析
      • 7.3代码实现
    • 八.算法总结
    • 后言

前言

哈喽,各位小伙伴大家好!今天给大家分享的是入门算法双指针。算法我们程序员必备的技能。话不多说,咱们进入正题!向大厂冲锋!

一.移动零

1.1题目

  • 题目:移动零

1.2思路分析

这里我们无非就是想让数组维持非0元素在前,0元素在后的区间状态。同时不改变非0元素的相对顺序。那我们可以用区间思想,借助双指针维护我们的区间状态。

1.3代码实现

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        for(int cur=0,dest=-1;cur<nums.size();cur++)//初始化同时扫描数组
        {
            if(nums[cur])//判断是否非0
            {
                swap(nums[++dest],nums[cur]);//dest移动后交换
            }
        }
    }
};
//分成三个区间未处理区
//处理区分区为非0元素区和0元素区

二.复写零

2.1题目

  • 题目:复写零

2.2思路分析

我们从左往右无法复写,因为会覆盖后面的数据。但是从右往左复写可以。所以我们找到最后一个复写的数,处理一下特殊情况从右往左复写即可。

2.3代码实现

class Solution {
public:
    void duplicateZeros(vector<int>& arr) 
    {
        int dest=-1,cur=0,n=arr.size();
        while(dest<n-1)//找到最后一个复写数
        {
            if(arr[cur]==0)
            {
                dest++;
            }
            dest++;
            if(dest>=n-1)
            {
                break;
            }
            cur++;
        }
        if(dest==n)//防止越界
        {
            arr[--dest]=0;
            dest--;
            cur--;
        }
        while(cur>=0)//从后往前复写
        {
            if(arr[cur]==0)
            {
                arr[dest--]=0;
                arr[dest--]=0;
                cur--;
            }
            else
            {
                arr[dest--]=arr[cur--];
            }
        }
    }
};

三.快乐数

3.1题目

  • 题目:
    快乐数

3.2思路分析

这里我们根据鸽巢原理就可以把题目转化为判断入环点是否为1。
具体快慢指针相遇的问题可以看这篇 快慢指针相遇证明

3.3代码实现

这里我们用两个变量代替指针的作用。

class Solution {
public:
        int bitSum(int n)//计算每个数的平方和
        {
            int sum=0;
            while(n)
            {
                sum+=pow(n%10,2);
                n/=10;
            }
            return sum;
        }
        bool isHappy(int n) {
        int slow=bitSum(n);
        int fast=bitSum(slow);
        while(slow!=fast)
        {
            slow=bitSum(slow);
            fast=bitSum(fast);
            fast=bitSum(fast);
        }
        return slow==1;//判断入环点是否为1
    }
};

四.盛水最多的容器

4.1题目

  • 题目:盛水最多的容器

4.2思路分析

这里我们需要观察规律解题。

4.3正确性证明

4.4代码实现

class Solution {
public:
        int maxArea(vector<int>& height)
        {
            int max=0;
            int left=0,right=height.size()-1;
            while(left<right)//双指针法
            {
            int v=fmin(height[left],height[right])*(right-left);//保存枚举的最大值
            max=fmax(v,max);//更新最大值
            height[left]<height[right]?left++:right--;
        }
        return max;
    }
};

五.有效三角形个数

5.1题目

  • 题目:有效三角形的个数

5.2思路分析

这里我们用排序的单调性做优化.

正确性证明上一个题解有,这里就不过多赘述了。

5.3代码实现

class Solution {
public:
    int triangleNumber(vector<int>& nums) 
    {
      int ret=0;
      sort(nums.begin(),nums.end());
      for(int i=nums.size()-1;i>=2;i--)//固定最大的数
      {
          int left=0,right=i-1;
          while(left<right)
          {
              int t=nums[left]+nums[right];
              if(t>nums[i])//大于
              {
                ret+=(right-left);
                right--;
              }
              else//小于
              {
                left++;
              }
          }
       }
       return ret;
    }  
};

六.两数之和

6.1题目

  • 题目:两数之和
    这里题目改了但是题意是一样的

6.2思路分析

这里依旧是按照单调性优化。

需要注意的是如果我们找到存在多个结果,我们找到结果后让left和right指针继续移动查找即可。

6.3代码实现

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) 
    {
        sort(nums.begin(),nums.end());//排序
        int left=0,right=nums.size()-1;
        while(left<right)
        {
            int tmp=nums[left]+nums[right];
            if(tmp<target)
            {
                left++;
            }
            else if(tmp>target)
            {
                right--;
            }
            else //找到结果
            {
                return {nums[left],nums[right]};
            }
        }
        return {};
    }
};

七.三数之和

7.1题目

  • 题目:三数之和

7.2思路分析

这里我们可以转化为两数之和来解决问题。但是要注意去重的问题。

7.3代码实现

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) 
    {
        vector<vector<int>> ret;
        sort(nums.begin(),nums.end());
        for(int i=0;i<nums.size()-2;)//固定最左边的指针
        {
            if(nums[i]>0)//大于没结果
            {
                break;
            }
            int left=i+1,right=nums.size()-1;
            int target=-nums[i];//找两数之和
            while(left<right)//左右指针两数之和,先移动再比较
            {
                int tmp=nums[left]+nums[right];
                if(tmp<target)//小于
                {
                    left++;
                    while(left<right&&nums[left]==nums[left-1])//跳过重复元素去重
                    {
                        left++;
                    }
                }
                else if(tmp>target)//大于
                {
                    right--;
                    while(left<right&&nums[right]==nums[right+1])//跳过重复元素去重
                    {
                        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--;
                    }
                }
            }
            i++;
            while(i<nums.size()&&nums[i]==nums[i-1])//跳过重复元素去重
            {
                    i++;
            }
            //去重
        }
        return ret;
    }
};

八.算法总结

双指针算法总体来说就是利用两个指针,根据题目要求灵活结合单调性,区间思想,以及题目场景用指针的移动访问解决问题。总而言之,双指针需要根据题目灵活使用解决问题

后言

这就是双指针算法原理的深度剖析,这些题目基本包含了双指针的所有解题方法。大家自己好好消化。感谢大家的耐心垂阅!今天就分享到这,咱们下期见!拜拜~

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

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

相关文章

微服务实战——ElasticSearch(保存)

商品上架——ElasticSearch&#xff08;保存&#xff09; 0.商城架构图 1.商品Mapping 分析&#xff1a;商品上架在 es 中是存 sku 还是 spu &#xff1f; 检索的时候输入名字&#xff0c;是需要按照 sku 的 title 进行全文检索的检索使用商品规格&#xff0c;规格是 spu 的…

基于Springboot+Vue的小区停车场管理系统登录(含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 在这个…

uniapp 微信发布注意事项

uniapp的微信播放不支持本地文件&#xff0c;起始微信原生语言是支持的 所以在编写uniapp代码时 要写两套逻辑 // #ifdef MP-WEIXIN 微信原封不变的自己写法 //#endif // #ifndef MP-WEIXIN 其他写法 //#endif 这样可实现 发布到微信后 微信原封不动的使用自己写…

初识算法 · 双指针(3)

目录 前言&#xff1a; 和为s的两数之和 题目解析&#xff1a; ​编辑 算法原理&#xff1a; 算法编写&#xff1a; 三数之和 题目解析 算法原理 算法编写 前言&#xff1a; 本文通过介绍和为S的两数之和&#xff0c;以及三数之和&#xff0c;对双指针算法进行深一步…

进度条(倒计时)Linux

\r回车(回到当前行开头) \n换行 行缓冲区概念 什么现象&#xff1f; 什么现象&#xff1f;&#xff1f; 什么现象&#xff1f;&#xff1f;&#xff1f; 自己总结&#xff1a; #pragma once 防止头文件被重复包含 倒计时 在main.c中&#xff0c;windows.h是不可以用的&…

Windows 环境搭建 CUDA 和 cuDNN 详细教程

CUDA CUDA&#xff08;Compute Unified Device Architecture&#xff09;是由NVIDIA公司推出的一个并行计算平台和编程模型&#xff0c;它允许开发者使用NVIDIA GPU进行通用计算&#xff08;即GPGPU&#xff09;&#xff0c;从而加速各种计算密集型任务。CUDA提供了一套基于C/C…

linux文件编程_线程

1. 基本概念 1.1. 进程与线程的概念 典型的UNIX/linux进程可以看成是只有一个控制线程&#xff0c;一个进程在同一时刻只做一件事情&#xff0c;有了多个控制线程后&#xff0c;在程序设计时可以把进程设计成在同一时刻做不止一件事&#xff0c;每个线程各自处理独立的任务。…

Web安全 - 文件上传漏洞(File Upload Vulnerability)

文章目录 OWASP 2023 TOP 10导图定义攻击场景1. 上传恶意脚本2. 目录遍历3. 覆盖现有文件4. 文件上传结合社会工程攻击 防御措施1. 文件类型验证2. 文件名限制3. 文件存储位置4. 文件权限设置5. 文件内容检测6. 访问控制7. 服务器配置 文件类型验证实现Hutool的FileTypeUtil使用…

STM32使用Keil5 在运行过程中不复位进入调试模式

一、选择Options for Target进入设置 二、选择所使用的调试器&#xff0c;这里以ST-Link为例。取消勾选Load Application at Startup 可以在进入调试模式的时候不会从新加载程序&#xff01;从而不破坏现场 三、点击Setting进入 四、取消勾选Reset after Connect 使得调试器连接…

探索 aMQTT:Python中的AI驱动MQTT库

文章目录 探索 aMQTT&#xff1a;Python中的AI驱动MQTT库背景介绍aMQTT是什么&#xff1f;如何安装aMQTT&#xff1f;简单库函数使用方法场景应用常见问题及解决方案总结 探索 aMQTT&#xff1a;Python中的AI驱动MQTT库 背景介绍 在物联网和微服务架构的浪潮中&#xff0c;MQ…

Redis:string类型

Redis&#xff1a;string类型 string命令设置与读取SETGETMSETMGET 数字操作INCRINCRBYDECRDECRBYINCRBYFLOAT 字符串操作APPENDSTRLENGETRANGESETRANGE 内部编码intembstrraw 在Redis中&#xff0c;字符串string存储的是二进制&#xff0c;以byte为单位&#xff0c;输入的二进…

ICPC-day1(NTT)

NTT经典例题 CCPC-Winter-Camp-day6-A——NTT经典例题 对于上面格式&#xff0c;如果想求出每个i的值可以使用卷积求出&#xff0c;因为阶乘j和阶乘i-j相乘的值为(i(i-j))i 补充一个二次剩余定理 P5491 【模板】二次剩余 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) //#in…

【MySQL】DML数据操作语句和基本的DQL语句

目录 一、Mysql对数据的增删改 1. 增加数据 2. 修改数据&#xff08;UPDATE语句&#xff09; 3. 删除 3.1 delete、truncate、drop区别 二、DQL语言&#xff08;重点&#xff09; 1. 单表查询 1.1 最简单的查询 1.2 从表中获取数据 1.3 字段名起别名 1.4 添加字段 1…

[20231103消息] 大模型商业化模式详解:烧钱之后如何挣钱?

距ChatGPT3.5发布已近一年&#xff0c;大模型狂热开始逐步降温&#xff1a;GPU禁运及长期烧钱的事实&#xff0c;让国内的大模型企业&#xff0c;不得不加速商业化考量。 目前&#xff0c;大模型的B端应用已经出现各种定价方法&#xff0c;包括按照时间段收费、按调用量收费以…

class 030 异或运算的骚操作

这篇文章是看了“左程云”老师在b站上的讲解之后写的, 自己感觉已经能理解了, 所以就将整个过程写下来了。 这个是“左程云”老师个人空间的b站的链接, 数据结构与算法讲的很好很好, 希望大家可以多多支持左程云老师, 真心推荐. https://space.bilibili.com/8888480?spm_id_f…

Java中Map和Set详细介绍,哈希桶的实现

大家好呀&#xff0c;前一节我们接触了二叉搜索树&#xff0c;那么紧接着&#xff0c;我们要学习一种十分重要而且也是我们在初阶数据结构中接触的最后一种数据结构—Map和Set&#xff0c;本篇博客将会详细介绍两种数据结构&#xff0c;并且针对哈希表底层实现一个哈希桶&#…

基于元神操作系统实现NTFS文件操作(三)

1. 背景 本文主要介绍DBR的读取和解析&#xff0c;并提供了基于元神操作系统的实现代码。由于解析DBR的目的是定位到NTFS磁盘分区的元文件$Root进行文件操作&#xff0c;所以只解析了少量的部分&#xff0c;其它部分可以参考相关文档进行理解。 DBR存在于磁盘分区的第一个扇区…

《数据结构》--链表【包含跳表概念】

不知道大家对链表熟悉还是陌生&#xff0c;我们秉着基础不牢&#xff0c;地动山摇的原则&#xff0c;会一点点的介绍链表的&#xff0c;毕竟链表涉及的链式存储也很重要的。在这之前&#xff0c;我们认识过顺序存储的顺序表&#xff0c;它其实就是一个特殊的数组。那链表到底是…

树莓派 AI 摄像头(Raspberry Pi AI Camera)教程

系列文章目录 前言 人们使用 Raspberry Pi 产品构建人工智能项目的时间几乎与我们生产 Raspberry Pi 的时间一样长。随着我们发布功能越来越强大的设备&#xff0c;我们能够支持的原生应用范围也在不断扩大&#xff1b;但无论哪一代产品&#xff0c;总会有一些工作负载需要外部…