算法思想总结:双指针算法

一、移动零

. - 力扣(LeetCode) 移动零

该题重要信息:1、保持非0元素的相对位置。2、原地对数组进行操作

 思路:双指针算法

class Solution {
public:
    void moveZeroes(vector<int>& nums)
    {
         int n=nums.size();
         for(int cur=0,des=-1;cur<n;++cur)
               if(nums[cur])//如为非零,就要与des后面的位置元素进行交换
                  swap(nums[++des],nums[cur]);
    }
};

 二、复写零

. - 力扣(LeetCode)复写零

该题的重要信息:1、不要在超过该数组的长度的位置写入元素(就是不要越界)2、就地修改(就是不能创建新数组)。3、不返回任何东西。

 思路:双指针算法

class Solution {
public:
    void duplicateZeros(vector<int>& arr)
    {
        int cur=0,des=-1,n=arr.size();
        //找最后一个被复写数的位置
        for(;cur<n;++cur)
        {
            if(arr[cur])
            ++des;
            else
            des+=2;
            if(des>=n-1)//要让des指向最后一个位置
            break;
        }
        //边界修正
        if(des==n)
        {
            arr[--des]=0;
            --des;
            --cur;
        }
        //从后往前复写
        for(;cur>=0;--cur)
        {
            if(arr[cur])
            arr[des--]=arr[cur];
            else
            {
                arr[des--]=0;
                arr[des--]=0;
            }
        }
    }
};

 三、快乐数

. - 力扣(LeetCode)快乐数

 该题的关键是:将正整数变成他的每位数的平方之和,有可能会一直循环始终到不了1,也有始终是1(快乐数)

思路:快慢双指针算法

以上的两个结论在博主的关于链表带环追击问题的文章里面有分析

顺序表、链表相关OJ题(2)-CSDN博客

class Solution {
public:
    int bitsum(int n)
    { 
        int sum=0;
        while(n)
        {
            int t=n%10;
            sum+=t*t;
            n/=10;//最后一位算完后拿掉
        }
        return sum;
    }

    bool isHappy(int n) 
    {
        int slow=n,fast=bitsum(n);
        while(fast!=slow)
        {
            slow=bitsum(slow);
            fast=bitsum(bitsum(fast));
        }
        return slow==1;
    }
};

四、盛最多水的容器

. - 力扣(LeetCode)盛最多水的容器

思路1、暴力枚举(时间复杂度太高)

class Solution {
public:
    int maxArea(vector<int>& height)
    {
        //暴力枚举
        int n=height.size();
        int ret=0;
          for(int i=0;i<n;++i)
             for(int j=i+1;j<n;++j)
                   ret=max(ret,min(height[i],height[j])*(j-i));
        return ret;
    }
};

思路2、双指针对撞算法

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

五、有效三角形的个数

. - 力扣(LeetCode)有效三角形的个数

 思路1:升序+暴力枚举

思路2:升序+利用双指针算法

class Solution {
public:
    int triangleNumber(vector<int>& nums) 
    {
        //排序一下
        sort(nums.begin(),nums.end());
        //先固定一个数,然后用双指针去找比较小的两个数
        int n=nums.size(),ret=0;
         for(int i=n-1;i>=2;--i)
         {
            int left=0,right=i-1;
            while(left<right)
            {
                int sum=nums[left]+nums[right];
                if(sum<=nums[i])  ++left;
                else  
                {
                    ret+=(right-left);
                    --right;
                } 
            }
         }
         return ret;
    }
};

 六、查找总价格为目标值的两个商品

. - 力扣(LeetCode)查找总价格为目标值的两个商品

 

思路1:两层for循环找到所有组合去计算

思路2:利用单调性,使用双指针算法解决问题

class Solution {
public:
    vector<int> twoSum(vector<int>& price, int target) 
    {
           int n=price.size();
           int left=0,right=n-1;
           while(left<right)
           {
               int sum=price[left]+price[right];
               if(sum>target) --right;
               else if(sum<target) ++left;
               else return {price[left],price[right]};
           }
           return {1,0};
    }
};

七、三数之和

. - 力扣(LeetCode)三数之和

解法1:排序+暴力枚举+set去重

解法2:排序+双指针

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums)
    {
        vector<vector<int>> ret;
        int n=nums.size();
        //先排序
        sort(nums.begin(),nums.end());
        //先固定一个数
        for(int i=0;i<n;)
        {
             if(nums[i]>0) break;//小优化
            int target =-nums[i];//目标值
            //定义双指针
            int left=i+1,right=n-1;
            while(left<right)
            {
                int sum=nums[left]+nums[right];
                if(sum<target)  ++left;
                else if(sum>target) --right;
                else  
                {
                   ret.push_back({nums[left],nums[right],nums[i]});//插入进去
                   ++left;
                   --right;
                   //去重
                   while(left<right&&nums[left]==nums[left-1])  ++left;//去重要注意边界
                   while(left<right&&nums[right]==nums[right+1])  --right;
                }
            }
            ++i;
            while(i<n&&nums[i]==nums[i-1])  ++i;//去重要注意边界
        }
               return ret;
    }
};

八、四数之和

. - 力扣(LeetCode)四数之和

 

解法1:排序+暴力枚举+set去重

解法2:排序+双指针(和上一题基本一样,无非就是多固定了一个数)

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) 
    {
       vector<vector<int>> ret;
       //先进行排序
       sort(nums.begin(),nums.end());
       //利用双指针解决
       int n=nums.size();
       //先固定一个数
       for(int i=0;i<n;)
       {
          //再固定一个数
          for(int j=i+1;j<n;)
          {
            int left=j+1,right=n-1;
            long long aim=(long long)target-nums[i]-nums[j];//确保不超出范围
            while(left<right)
            {
             long long sum=nums[left]+nums[right];
            if(sum<aim)  ++left;
            else if(sum>aim) --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;
            }
            }
             //去重
          ++j;
          while(j<n&&nums[j]==nums[j-1]) ++j;
          }
          //去重
          ++i;
          while(i<n&&nums[i]==nums[i-1]) ++i;
          }
          return ret;
    }
};

九、总结

常见的双指针有三种形式:前后指针、对撞指针、快慢指针

1、前后指针:用于顺序结构,一般是两个指针同方向,cur指针用来遍历数组,des指针将数组进行区域划分。(如1、2题)

       注意事项:如果是从前往后遍历,要注意dst不能走得太快,否则cur还没遍历到一些数就会被覆盖掉,必要时候可以根据情况从后往前遍历。

2、快慢指针:其基本思想就是使⽤两个移动速度不同的指针在数组或链表等序列结构上移动。
这种⽅法对于处理环形链表或数组⾮常有⽤。(如第3题,以及链表带环的问题)

        注意事项: 其实不单单是环形链表或者是数组,如果我们要研究的问题出现循环往复的情况时,均可考虑使⽤快慢指针的思想。最常用的就是快指针走两步,慢指针走一步。

3、对撞指针:一般用于顺序结构。从两端向中间移动。⼀个指针从最左端开始,另⼀个从最右端开始,然后逐渐往中间逼近。并且常常会用到单调性!!(如4-8题)
        注意事项:对撞指针的终⽌条件⼀般是两个指针相遇或者错开(也可能在循环内部找到结果直接跳出循环)

        如果后面还有关双指针的经典题目,博主会继续在这篇更新的!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

手把手写深度学习(23):视频扩散模型之Video DataLoader

手把手写深度学习(0)&#xff1a;专栏文章导航 前言&#xff1a;训练自己的视频扩散模型的第一步就是准备数据集&#xff0c;而且这个数据集是text-video或者image-video的多模态数据集&#xff0c;这篇博客手把手教读者如何写一个这样扩散模型的的Video DataLoader。 目录 准…

挑战杯 多目标跟踪算法 实时检测 - opencv 深度学习 机器视觉

文章目录 0 前言2 先上成果3 多目标跟踪的两种方法3.1 方法13.2 方法2 4 Tracking By Detecting的跟踪过程4.1 存在的问题4.2 基于轨迹预测的跟踪方式 5 训练代码6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习多目标跟踪 …

4G安卓核心板T310_紫光展锐平台方案

紫光展锐T310应用 DynamlQ架构 12nm 制程工艺&#xff0c;采用 1*Cortex-A753*Cortex-A55处理器&#xff0c;搭载Android11.0操作系统&#xff0c;主频最高达2.0GHz.此外&#xff0c;DynamlQ融入了AI神经网络技术&#xff0c;新增机器学习指令&#xff0c;让其在运算方面的机器…

绝对省事!多微信聚合聊天神器大揭秘!

在如今社交网络发达的时代&#xff0c;微信已成为人们生活中不可或缺的通讯工具。然而&#xff0c;对于拥有多个微信账号的用户来说&#xff0c;经常需要来回切换不同账号&#xff0c;给日常使用带来一定的不便。 那么&#xff0c;有没有一种办法能够让我们摆脱这种繁琐的操作…

掼蛋-掌握出牌权

掼蛋游戏中&#xff0c;出牌权往往能决定一局牌的走向&#xff0c;掌握出牌权可以主动控制局势。出牌权是指在每一轮的出牌环节中谁先出牌。出牌权的重要性主要体现在以下两个方面&#xff1a; 一、控制节奏 出牌权可以让我们主动控制游戏的节奏&#xff0c;可以根据自己的出牌…

Post请求出现Request header is too large

问题描述&#xff1a; 在做项目的时候&#xff0c;前端请求体太大的时候&#xff0c;出现Request header is too large问题&#xff0c;后端接口如下&#xff1a; 前端请求接口返回问题如下&#xff1a; 解决方案&#xff1a; 问题原因&#xff1a;这是因为我们在做Springboo…

BUG:RuntimeError: input.size(-1) must be equal to input_size. Expected 1, got 3

出现的bug为:RuntimeError: input.size(-1) must be equal to input_size. Expected 1, got 3 出现问题的截图: 问题产生原因:题主使用pytorch调用的nn.LSTM里面的input_size和外面的数据维度大小不对。问题代码如下: self.lstm nn.LSTM(input_size, hidden_size, num_laye…

计算机网络-第6章 应用层(2)

6.5 电子邮件 电子邮件&#xff0c;把邮件发送到收件人使用的邮件服务器&#xff0c;并放在其中的收件人邮箱中。最重要的两个标准&#xff1a;简单邮件传送协议SMTP&#xff0c;互联网文本报文格式。 SMTP只能传7位ASCII码邮件&#xff0c;93年提出互联网邮件扩充MIME。邮件…

关于YOLOv9去掉辅助分支脚本使用的一些说明。

专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;主力高效涨点&#xff01;&#xff01;&#xff01; B站链接&#xff1a;YOLOv9去除辅助训练分支&#xff01;_哔哩哔哩_bilibili 一、说明 在subbranch_removal.py脚本中&#xff0c;我们需要填入上方…

新西兰 eSIM 卡 ONE NZ充值、激活

新西兰One NZ 保号规则和费用 先说大家比较关注的保号条件和费用吧。 新买的卡有效期 720 天&#xff0c;能够充值续期&#xff0c;但是充值后的有效期反而变为 360 天&#xff08;用于保号的兄弟就快过期再充值&#xff09;如果到期后不去充值&#xff0c;账户将变为非活跃状…

SAP 工单CO02 TECO时检查的增强BADI:WORKORDER_UPDATE

需求&#xff1a;需要在CO02进行TECO时检查一下 第三代增强&#xff1a;BADI&#xff1a;WORKORDER_UPDATE中的REORG_STATUS_ACT_CHECK方法 第一步&#xff1a;SE19输入BADI&#xff0c;然后创建 填入名称&#xff1a;ZWORKORDER_UPDATE和描述 输入类名&#xff1a;ZCL_WORKORD…

C语言函数—自定义函数

如果库函数能干所有的事情&#xff0c;那还要程序员干什么&#xff1f; 所有更加重要的是自定义函数。 自定义函数和库函数一样&#xff0c;有函数名&#xff0c;返回值类型和函数参数。 但是不一样的是这些都是我们自己来设计。 这给程序员一个很大的发挥空间。 函数的组…

第十四届蓝桥杯蜗牛

蜗牛 线性dp 目录 蜗牛 线性dp 先求到达竹竿底部的状态转移方程 求蜗牛到达第i根竹竿的传送门入口的最短时间​编辑 题目链接&#xff1a;蓝桥杯2023年第十四届省赛真题-蜗牛 - C语言网 关键在于建立数组将竹竿上的每个状态量表示出来&#xff0c;并分析出状态转移方程 in…

在Linux中进行OpenSSH升级

由于OpenSSH有严重漏洞&#xff0c;因此需要升级OpenSSH到最新版本。 OpenSSL和OpenSSH都要更新&#xff0c;OpenSSH依赖于OpenSSL。 第一步&#xff0c;查看当前的OpenSSH服务版本。 命令&#xff1a;ssh -V 第二步&#xff0c;安装、启动telnet&#xff0c;关闭安全文件&a…

免费AI软件开发工具测评:iFlyCode VS CodeFlying

前言 Hello&#xff0c;各位看官&#xff0c;今天为大家带来两款人工智能的软件开发工具的测评&#xff0c;他们分别是iFlyCode和CodeFlying&#xff0c;我相信当大家看到这两款产品名字的时候不禁都会有些好奇&#xff0c;两个产品都有Code 和Fly两个元素&#xff0c;那他们之…

Python语言在编程业界的地位——《跟老吕学Python编程》附录资料

Python语言在编程业界的地位——《跟老吕学Python编程》附录资料 ⭐️Python语言在编程业界的地位2024年3月编程语言排行榜&#xff08;TIOBE前十&#xff09; ⭐️Python开发语言开发环境介绍1.**IDLE**2.⭐️PyCharm3.**Anaconda**4.**Jupyter Notebook**5.**Sublime Text** …

若依上传文件/common/upload踩坑

前言&#xff1a;作者用的mac系统&#xff08;这个是个坑&#xff09;&#xff0c;前端用的uniapp&#xff0c;调用若依通用上传方法报错NoSuchFileException: /home/ruoyi/uploadPath/upload... 前端上传代码示例如下: uni.chooseImage({count: 1,success(res){ uni.uploa…

在centos8中部署Tomcat和Jenkins

参考链接&#xff1a;tomcat安装和部署jenkins_jenkins和tomcat-CSDN博客 1、进入centos中 /usr/local 目录文件下 [rootlocalhost webapps]# cd /usr/local2、使用通过wget命令下下载tomcat或者直接在官网下载centos版本的包后移动到centos中的local路径下 3、下载tomcat按…

1307页字节跳动Android面试全套真题解析在互联网火了-,完整版开放下载

多进程带来的问题 AIDL 使用浅析binder 原理解析binder 最底层解析多进程通信方式以及带来的问题多进程通信方式对比 Android 高级必备 &#xff1a;AMS,WMS,PMS AMS,WMS,PMS 创建过程 AMS,WMS,PMS全解析AMS启动流程WindowManagerService启动过程解析PMS 启动流程解析 A…

PyTorch之完整的神经网络模型训练

简单的示例&#xff1a; 在PyTorch中&#xff0c;可以使用nn.Module类来定义神经网络模型。以下是一个示例的神经网络模型定义的代码&#xff1a; import torch import torch.nn as nnclass MyModel(nn.Module):def __init__(self):super(MyModel, self).__init__()# 定义神经…