专题一——双指针算法

news2024/11/28 0:57:53

原理:将数组进行区间划分,通过指针(下标)的移动实现题目所要求的区间(数组分块

(实现代码统一是C++)

建议在做题与看题解时要自己反复模拟这个实现的过程,以后在做题做到类似的题才能举一反三!

一移动零

链接:283. 移动零 - 力扣(LeetCode)

思路:将要实现的区间用指针划为不同的区间(非0区间与0区间)再进行指针的搜索。

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int cur=-1,des=0;//cur固定,des去进行数组的扫描,即找非0元素
        //最后:[0,cur]为非0元素[cur+1,des]为0元素
        while(des<nums.size())
        {
            if(nums[des]!=0)
            {
                swap(nums[cur+1],nums[des]);
                cur++;
            }
            des++;
        }
    }
};

二复写零

链接:1089. 复写零 - 力扣(LeetCode)

思路:

确定目标位置:首先,使用两个指针 dest 和 cur 来确定每个位置复制0后应该放置的位置。cur 指针用于遍历原始数组,而 dest 指针则用于确定在复制0后应该放置新元素的位置。

cur 最终的位置就是复写后数组的最后一个数的位置。

再从后往前进行数组值的覆盖(从前向后遍历会导致数组后面元素丢失)

class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        int cur=0,des=-1,n=arr.size();
        while(des<n)
        {
            //arr[cur+1]==0...如果在cur=0位置上是0呢?
            if(arr[cur]==0)
            {
                des+=2;
            }
            else
            {
                des++;
            }
            if(des>=n-1)
            {
                break;
            }
            cur++;
        }
        //[1,0,2,3,0,4]des走到n位置越界
        if(des>n-1)
        {
            //直接让des在数组的最后一个位置上并把它赋为0(越界情况一定是在复写0的时候越界的!)
            des=n-1;
            arr[des--]=0;
            cur--;
        }
        //cur的位置是要实现的数组的最终位置

        while(cur>=0)
        {
            //(cur的位置遇到0就让des进行复写0的操作)
            if(arr[cur]==0)
            {
                arr[des--]=0;
                arr[des--]=0;
                cur--;
            }
            //从后向左进行值的覆盖
            else
            {
                arr[des--]=arr[cur--];
            }
        }
    }
};

三快乐数

链接:202. 快乐数 - 力扣(LeetCode)

思路:由于鸽巢原理,最后必定会有两个数相等,形成闭环即:在某一时刻,只有两种情况:要么有数字等于1形成闭环,要么会有两个数是相等的!

那么我们可以使用在环形链表中一样使用快慢双指针来进行解答 

class Solution {
public:
    //函数实现每一位数平方和相加
    int bitsum(int n)
    {
        int sum=0;
        while(n)
        {
            sum+=pow(n%10,2);
            n/=10;
        }
        return sum;
    }
    //类似环形链表首先想到快慢双指针
    //不管最后有没有结果等于1,都一定会有两个数相等形成闭环(重复循环)
    //slow与fast一定在某个时刻相等 
    bool isHappy(int n) 
    {
        int slow=n,fast=n;
        while(slow!=1)
        {
            slow=bitsum(slow);
            fast=bitsum(bitsum(fast));
            if(slow==fast)
            {
                break;
            }
        }
        return slow==1;
    }
};

四盛最多水的容器

oj链接:11. 盛最多水的容器 - 力扣(LeetCode)

 思路:使用两个指针,一个在最左一个在最右,算出结果进行调整移动时,要移动两个中最小的那一个(短板效应),在各种结果中找出最大的容器即为题目所求

class Solution {
public:
    int maxArea(vector<int>& height) {
        //ret存储的是最多容纳的水
        int left=0,right=height.size()-1,ret=INT_MIN;
        while(left<right)
        {
            //更新ret的值始终保持是所有盛水容器当中最大的
            ret=max(ret,(right-left)*min(height[left],height[right]));
            //要去移动最小的高
            //如果是移到最大的:距离在减小(高度是按最小的来算的),结果只会是减不会增
            if(height[left]<height[right])
            {
                left++;
            }
            else
            {
                right--;
            }
        }
        return ret;
    }
};

五有效三角形的个数 

oj链接:611. 有效三角形的个数 - 力扣(LeetCode)

思路:先对数组进行排升序,排序后要先固定最大的那个值,然后就可以用双指针算法来解决问题:(与上面的思路大致相同) 

class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        //先将数组进行排升序
        sort(nums.begin(),nums.end());
        int count=0,left=0,right=0;
        //固定最后一个数(最大的数nums[i])
        for(int i=nums.size()-1;i>=0;i--)
        {
            //一定left,最大的数左边right进行移动
            left=0,right=i-1;
            while(left<right)
            {
                //两个数相加<=最大的数则要移动left使得和变大
                if(nums[left]+nums[right]<=nums[i])
                {
                    left++;
                }
                else
                {
                    //left向后无论怎么移动,和一定>nums[i]即满足三角形任意两者之和大于第三边
                    count+=right-left;
                    right--;
                }
            }
        }
        return count;
    }
};

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

 oj链接:LCR 179. 查找总价格为目标值的两个商品 - 力扣(LeetCode)

思路与上面大体一致,比较简单这里就不写了

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

七三数之和

oj链接:LCR 007. 三数之和 - 力扣(LeetCode)

思路:与有效三角形的个数类似:先固定一个数,再使用双指针进行移动找到:nums[left]+nums[right]==-固定数。但实现起来要考虑两个细节:

1不漏:在找到符合值后,两个指针不要‘停’,继续靠拢进行查找;

2去重:找到后要判断在接下来移动的时候是否会遇到重复数(遇到就直接跳过)

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        //C++直接开辟二维数组
        vector<vector<int>> ans;
        int left=0,right=0,n=nums.size();
        //固定最左边一个数,在利用二数先加的题的思路去实现
        //但要考虑:1不漏 2去重
        for(int i=0;i<n;)
        {
            if(nums[i]>0)
            {
                break;
            }
            left=i+1,right=n-1;
            while(left<right)
            {
                if(nums[left]+nums[right]>-nums[i])
                {
                    right--;
                }
                else if(nums[left]+nums[right]<-nums[i])
                {
                    left++;
                }
                else
                {
                    //C语言要开辟数组,这里直接push_back爽!!
                    ans.push_back({nums[left],nums[right],nums[i]});
                    //不漏
                    left++,right--;
                    //去重,判断while循环条件先在后面,否则会有越界风险
                    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 ans;
    }
};

对比用C语言写的:要进行对二维数组的开辟,非常麻烦!

/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */

int cmp(const void * a, const void * b)
{
   return ( *(int*)a - *(int*)b );
}
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
    *returnSize=0;//初始化
    //排序
    qsort(nums,numsSize,sizeof(int),cmp);

    //为规定的返回值创建类型相同的数组
    int** ans=(int**)malloc(sizeof(int*)*numsSize*numsSize);

    //返回数组的数组要malloc
    *returnColumnSizes=(int*)malloc(sizeof(int)*numsSize*numsSize);

    //参考两数之和利用双指针算法,但要考虑去重,数组越界问题
    for(int i=0;i<numsSize;)
    {
        int begin=i+1,end=numsSize-1,target=nums[i];

        //如果固定的值>0,那么三数相加就不可能=0(小优化)
        if(target>0) break;

        //在固定值后,在[begin,end]的区间内进行查找
        while(begin<end)
        {
            if(nums[begin]+nums[end]==-target)
            {
                //二级数组ans中malloc存储三元数组的值(类似坐标的方式进行表达)
                ans[*returnSize]=(int*)malloc(sizeof(int)*3);
                //要返回数量的大小
                (*returnColumnSizes)[*returnSize]=3;
                ans[*returnSize][0]=nums[begin];
                ans[*returnSize][1]=nums[end];
                ans[*returnSize][2]=target;
                (*returnSize)++;
                begin++;
                end--;
                //[0,0,0,0,0]
                while(begin<end && nums[begin]==nums[begin-1]) begin++;
                while(begin<end && nums[end]==nums[end+1]) end--;
            }
            else if(nums[begin]+nums[end]>-target) end--;
            else if(nums[begin]+nums[end]<-target) begin++;
        }
        i++;
        while(i<numsSize && nums[i]==nums[i-1]) i++;
    }
    return ans;
}

 八四数之和

oj链接:18. 四数之和 - 力扣(LeetCode)

思路:与三数之和类似,多个固定的数和溢出问题的解决

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        vector<vector<int>> ans;
        int left=0,right=0,n=nums.size(),sum=0;
        for(int i=0;i<n;)
        {
            for(int j=i+1;j<n;)
            {
                left=j+1,right=n-1;
                //处理数据溢出
               long long aim=(long long)target-nums[i]-nums[j];
                while(left<right)
                {
                    sum=nums[left]+nums[right];
                    if(sum<aim)
                    {
                        left++;
                    }
                    else if(sum>aim)
                    {
                        right--;
                    }
                    else
                    {
                        ans.push_back({nums[left],nums[right],nums[i],nums[j]});
                        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 ans;
    }
};

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

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

相关文章

QT6实现创建与操作sqlite数据库及读取实例(一)

一.Qt为SQL数据库提供支持的基本模块&#xff08;Qt SQL&#xff09; Qt SQL的API分为不同层&#xff1a; 驱动层 SQL API层 用户接口层 1.驱动层 对于Qt 是基于C来实现的框架&#xff0c;该层主要包括QSqlDriver&#xff0c;QSqlDriverCreator,QSqlDriverCreatorBase,QSqlPlug…

Linux第78步_使用原子整型操作来实现“互斥访问”共享资源

使用原子操作来实现“互斥访问”LED灯设备&#xff0c;目的是每次只允许一个应用程序使用LED灯。 1、创建MyAtomicLED目录 输入“cd /home/zgq/linux/Linux_Drivers/回车” 切换到“/home/zgq/linux/Linux_Drivers/”目录 输入“mkdir MyAtomicLED回车”&#xff0c;创建MyA…

Python从 Google 地图空气质量 API 获取空气污染数据

获取给定位置当前的空气质量 让我们开始吧!在本节中,我们将介绍如何使用 Google 地图获取给定位置的空气质量数据。您首先需要一个 API 密钥,可以通过您的 Google Cloud 帐户生成该密钥。他们有90 天的免费试用期,之后您将为您使用的 API 服务付费。在开始大量拨打电话之前…

51单片机中断信号的种类及应用场景

在嵌入式系统中&#xff0c;中断是一种重要的事件处理机制&#xff0c;它可以在程序执行的任何时候暂停当前任务&#xff0c;转而执行与之相关的特殊任务或事件。51单片机作为一种常见的微控制器&#xff0c;其中断功能在各种应用中起着关键作用。然而&#xff0c;对于初学者和…

一、SpringBoot基础搭建

本教程主要给初学SpringBoot的开发者&#xff0c;通过idea搭建单体服务提供手把手教学例程&#xff0c;主要目的在于理解环境的搭建&#xff0c;以及maven模块之间的整合与调用 源码&#xff1a;jun/learn-springboot 以商城项目为搭建例子&#xff0c;首先计划建1个父模块&…

部署单节点k8s并允许master节点调度pod

安装k8s 需要注意的是k8s1.24 已经弃用dockershim&#xff0c;现在使用docker需要cri-docker插件作为垫片&#xff0c;对接k8s的CRI。 硬件环境&#xff1a; 2c2g 主机环境&#xff1a; CentOS Linux release 7.9.2009 (Core) IP地址&#xff1a; 192.168.44.161 一、 主机配…

GPT-4 VS Claude3、Gemini、Sora:五大模型的技术特点与用户体验

【最新增加Claude3、Gemini、Sora、GPTs讲解及AI领域中的集中大模型的最新技术】 2023年随着OpenAI开发者大会的召开&#xff0c;最重磅更新当属GPTs&#xff0c;多模态API&#xff0c;未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义&#xff0c;不亚…

CTF题型 md5考法例题汇总

CTF题型 md5考法相关例题总结 文章目录 CTF题型 md5考法相关例题总结一.md5弱字符相等()[SWPUCTF 2021 新生赛]easy_md5 二.md5强字符相等()1)文件相等[2024 qsnctf 擂台赛 easy_md5]2)字符相等[安洵杯 2019]easy_web 三.md5哈希长度扩展攻击[NPUCTF2020]ezinclude文件包含利用…

深入技术细节:放弃Spring Security,自己实现Token权限控制!

最近做了个项目&#xff0c;大家都知道很多的项目都是在自己手上原本的框架内进行业务开发。但是甲方爸爸的这个项目需要交付原代码&#xff0c;并且要求框架逻辑简单清晰&#xff0c;二次开发简易上手。 那不是要重新从0到1写一套框架吗&#xff1f; 试着先给甲方爸爸报一下…

美食杂志制作秘籍:引领潮流,引领味蕾

美食杂志是一种介绍美食文化、烹饪技巧和美食体验的杂志&#xff0c;通过精美的图片和生动的文字&#xff0c;向读者展示各种美食的魅力。那么&#xff0c;如何制作一本既美观又实用的美食杂志呢&#xff1f; 首先&#xff0c;你需要选择一款适合你的制作软件。比如FLBOOK在线制…

Java微服务分布式事务框架seata的TCC模式

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 往期热门专栏回顾 专栏…

教大家使用vue实现 基础购物车。

首先我要知道一点 其能够数据变化的 都用{{}}来进行渲染类似 来看一下实现效果 实现思路 &#xff1a; 1&#xff0c;引进 vue.js 2,setup 将声明变量 方法放在setup里面 3&#xff0c;用响应式声明 ref&#xff08;&#xff09; 或rective声明 可以声明对象等等 let 也…

AST学习入门

AST学习入门 1.AST在线解析网站 https://astexplorer.net/ 1.type: 表示当前节点的类型&#xff0c;我们常用的类型判断方法t.is********(node)**,就是判断当前的节点是否为某个类型。 2**.start**:表示当前节点的开始位置 3.end:当前节点结束 4.loc : 表示当前节点所在的行…

产品推荐 | 基于Xilinx FPGA XC5VFX100T的6U VPX视频叠加板卡

01、产品概述 本板卡是基于Xilinx FPGA XC5VFX100T的6U VPX视频叠加板卡。主要用于视频叠加板具有多种高清图形输入接口&#xff0c;可实现其中两路高清视频信号的开窗显示和叠加显示功能&#xff1b;或者输出和输入图形接口的转换。 02、物理特性 ● 尺寸&#xff1a;6U CPC…

【文献阅读】AlphaFold touted as next big thing for drug discovery — but is it?

今天来精读2023年10月发在《Nature》上的一篇新闻&#xff1a;AlphaFold touted as next big thing for drug discovery — but is it? (nature.com)https://www.nature.com/articles/d41586-023-02984-w Questions remain about whether the AI tool for predicting protein …

Python Windows系统 虚拟环境使用

目录 1、安装 2、激活 3、停止 1、安装 1&#xff09;为项目新建一个目录&#xff08;比如&#xff1a;目录命名为learning_log&#xff09; 2&#xff09;在终端中切换到这个目录 3&#xff09;执行命令&#xff1a;python -m venv ll_env&#xff0c;即可创建一个名为ll…

常用的6个的ChatGPT网站,国内可用!

GPTGod &#x1f310; 链接&#xff1a; GPTGod &#x1f3f7;️ 标签&#xff1a; GPT-4 免费体验 支持API 支持绘图 付费选项 &#x1f4dd; 简介&#xff1a;GPTGod 是一个功能全面的平台&#xff0c;提供GPT-4的强大功能&#xff0c;包括API接入和绘图支持。用户可以选择免…

成都百洲文化传媒有限公司电商新浪潮的领航者

在当今电商行业风起云涌的时代&#xff0c;成都百洲文化传媒有限公司以其独特的视角和专业的服务&#xff0c;成为了众多商家争相合作的伙伴。今天&#xff0c;就让我们一起走进百洲文化的世界&#xff0c;探索其背后的成功密码。 一、百洲文化的崛起之路 成都百洲文化传媒有限…

短视频矩阵系统---php7.40版本升级自研

短视频矩阵系统---php7.40版本升级自研 1.部署及搭建 相对于其他系统&#xff0c;该系统得开发及部署难度主要在各平台官方应用权限的申请上&#xff0c;据小编了解&#xff0c;目前抖音短视频平台部分权限内侧名额已满&#xff0c;巧妇难为无米之炊&#xff0c;在做相关程序…

unity 添加newtonsoft-json

再git url上添加&#xff1a;com.unity.nuget.newtonsoft-json