【双指针精选题目】详解8道题

news2024/11/17 21:44:42

讲解【双指针系列】的8道经典练习题,有三道题在另一篇博客,文末已给出链接,在讲解题目的同时给出AC代码 

目录

双指针两种类型: 

1、移动零

2、复写零

3、快乐数

4、力扣11:盛最多水的容器

5、有效三角形的个数


双指针两种类型: 

常⻅的双指针有两种形式,一种是对撞指针,一种是快慢指针
①、对撞指针:一般用于顺序结构中,也称左右指针。
• 对撞指针从两端向中间移动。一个指针从最左端开始,另一个从最右端开始,然后逐渐往中间逼近。其终止条件一般是两个指针相遇或者错开(也可能在循环内部找到结果直接跳出循
环),也就是:

  •  left == right (两个指针指向同一个位置)
  •  left > right (两个指针错开)

②、快慢指针:又称为龟兔赛跑算法,其基本思想就是使用两个移动速度不同的指针在数组或链表等序列结构上移动。
这种方法对于处理环形链表或数组非常有用。其实不单单是环形链表或者是数组,如果我们要研究的问题出现循环往复的情况时,均可考虑使用快慢指针的思想。快慢指针的实现方式有很多种,最常用的一种就是:

  • 在一次循环中,每次让慢的指针向后移动一位,而快的指针往后移动两位,实现一快一慢。

1、移动零

拓展知识:

这种区间划分的思路适用于快排中的最核心一步:区间划分,我们假设基准值为tmp,此时只需把区间划分为<tmp的一个区间,>tmp的一个区间和待处理区间,就能完成区间划分 

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]);
    }
};

2、复写零

 这种在数组中移动元素,即操作数组中的元素一般我们也用双指针算法。

那么从左往右遍历不行,就试试从右往左遍历

注:上面的复写过程是假设用两个数组是为了方便演示,真正的过程是在一个数组中进行的。从上面可以知道cur一开始指向最后一个要被复写的数,即4【因为dest指向的那个数组中最后一个元素就是4,然后会从后往前遍历】,那么问题就要转化为①、找到最后一个复写的数 ②、从后往前复写

找最后一个复写的数时,cur一开始为0位置,dest一开始为-1位置

 特例处理:

注:这种半模拟半双指针的问题,一定要自己画图找出解决方案。

class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        //先找到最后一个要复写的数
        int cur = 0, dest = -1, n = arr.size();
        while (cur < n) //每次循环要先判断cur位置是否合法
        {
            //非0元素dest++,0元素dest+=2
            if (arr[cur]) dest++;
            else dest += 2;
            if (dest >= n - 1) break;//要么到了最后一个位置要么没到
            cur++;//没到cur继续往后走
        }
        //处理边界情况,判断dest是否越界
        if (dest > n - 1)
        {
            arr[n - 1] = 0;
            cur--, dest -= 2; 
        }
        //从后往前复写
        while (cur >= 0)//复写完0位置才算结束
        {
            if (arr[cur]) arr[dest--] = arr[cur--];
            else
            {
                arr[dest--] = 0;
                arr[dest--] = 0;
                cur--;
            }
        }
    }
};

3、快乐数

 这道题跟之前讲的环形链表题很像,建议先看我之前写过的文章:【数据结构】--单链表力扣面试题⑦环形链表-CSDN博客

证明过程可以参考【鸽巢原理】【抽屉原理】

与上面这道环形链表不同的地方在于本道题一定有环,那么代码就一点点不同罢了

class Solution {
public:
    int bitSum(int n) //返回n这个数每一位上的平方之和
    {
        int sum = 0;
        while (n)
        {
            sum += (n % 10) * (n % 10);
            n /= 10;
        }
        return sum;
    }
    bool isHappy(int n) {
        //用数来模拟快慢指针
        int slow = n, fast = bitSum(n);//slow指向第一个数,fast指向第二个数
        while (slow != fast)
        {
            slow = bitSum(slow);//slow往下走一步
            fast = bitSum(bitSum(fast));//fast往下走两步
        }
        return slow == 1;//最后一定会相遇的,因为就两种情况,直接判断==1则为true
    }
};

4、力扣11:盛最多水的容器

题目分析:

 ①、暴力求解肯定能解出来,但O(n*n)肯定过不了这道题,所以要找规律优化为O(n)

class Solution {
public:
    int maxArea(vector<int>& height) {
        int left = 0, right = height.size() - 1, ret = 0;
        while (left < right)
        {
            int v = min(height[left], height[right]) *  (right - left);
            ret = max(ret, v); //求出所有v中的最大值
            //数小的指针先动
            if (height[left] < height[right]) left++; 
            else right--;
        }
        return ret;
    }
};

5、有效三角形的个数

三层 for 循环枚举出所有的三元组,并且判断是否能构成三⻆形。
虽说是暴力求解,但还是可以优化一下:
判断三⻆形的优化:
如果能构成三角形,需要满足任意两边之和要大于第三边。但是实际上只需让较小的两条边
之和大于第三边即可。因此我们可以先将原数组排序,然后从小到大枚举三元组,一方面省去枚举的数量,另一方面方便判断是否能构成三角形。

但下面的暴力算法会超时

class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        //1、优化:先排序
        sort(nums.begin(), nums.end());

        //2、暴力解法
        int n = nums.size(), ret = 0;
        for (int i = 0; i < n; i++)
         for (int j = i + 1; j < n; j++)
            for (int k = j + 1; k < n; k++)
                if (nums[i] + nums[j] > nums[k])
                    ret++;

        return ret;
    }
};

 解法二【排序+双指针】

1、先将数组排序。
根据「解法一」中的优化思想,我们可以固定一个「最⻓边」,然后在比这条边小的有序数组中找出一个二元组,使这个二元组之和大于这个最⻓边。由于数组是有序的,我们可以利用「对撞指针」来优化。
2、设最⻓边枚举到 i 位置,区间 [left, right] 是i位置左边的区间(也就是比它小的区间):
◦ 如果 nums[left] + nums[right] > nums[i] :
▪ 说明 [left, right - 1] 区间上的所有元素均可以与 nums[right] 构成比nums[i] 大的二元组满足条件的有 right - left 种,此时 right 位置的元素的所有情况相当于全部考虑完毕, right-- ,进入下一轮判断
◦ 如果 nums[left] + nums[right] <= nums[i] :
▪ 说明 left 位置的元素是不可能与 [left + 1, right] 位置上的元素构成满足条件
的二元组,left 位置的元素可以舍去,left++ 进入下轮循环

class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        //1、优化:先排序
        sort(nums.begin(), nums.end());

        //2、双指针算法解决问题
        int n = nums.size(), ret = 0;
        //循环固定每次区间最大的数,下标最小为2,至少3个数才能判断是否为三角形
        for (int i = n - 1; i >= 2; i--)
        {
            //每固定完一个数,就进行一次循环
            int left = 0, right = i - 1;
           while (left < right)
           {
             if (nums[left] + nums[right] > nums[i]) ret += right - left, right--;
             else left++; 
           }
        }
        return ret;
    }
};

剩余三道题在另一篇博客:

【详解:两数之和&&三数之和&&四数之和】-CSDN博客

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

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

相关文章

Web端3D渲染引擎HOOPS SDK助力打造创新型3D测量软件

HOOPS SDK是全球领先的3D领域开发工具提供商Tech Soft 3D 打造的控件产品&#xff0c;HOOPS SDK包括4款3D软件开发工具&#xff0c;其中HOOPS Exchange是一款CAD数据转换工具&#xff0c;可读取和导入30多种CAD文件格式&#xff1b;HOOPS Communicator是一款专注于Web端工程图形…

螺旋数字矩阵 - 华为OD统一考试

OD统一考试(C卷) 分值: 100分 题解: Java / Python / C++ 题目描述 疫情期间,小明隔离在家,百无聊赖,在纸上写数字玩。他发明了一种写法: 给出数字个数n和行数m (0 < n <= 999,0 < m <= 999),从左上角的1开始,按照顺时针螺旋向内写方式,依次写出2,3……

R2机器人加载棋盘与棋子模型,对urdf、sdf的解释(区分srdf)

1、概述 urdf、sdf、srdf文件都属于xml的规范格式&#xff0c;解释分别如下&#xff1a;urdf(unified robot description format)叫做"统一机器人描述格式"&#xff0c;主要目的就是提供一种尽可能通用的机器人描述规范&#xff0c;这样对于机器人的描述就可以互相移…

代码随想录算法训练营第15天 | 102. 二叉树的层序遍历 + 226. 翻转二叉树 + 101. 对称二叉树

今日内容 102.层序遍历 226.翻转二叉树 101.对称二叉树 102.二叉树的层序遍历 - Medium 题目链接&#xff1a;力扣-102. 二叉树的层序遍历 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&…

Spark---行动算子RDD

文章目录 1.行动算子1.1 reduce1.2 collect1.3 first1.4 count1.5 take1.6 takeOrdered1.7 aggregate1.8 fold1.9 countByKey1.10 countByValue1.11 save 相关算子1.12 foreach 1.行动算子 Spark的行动算子是触发作业执行的方法&#xff0c;它们会直接触发计算并返回结果。 行…

OceanBase原生分布式数据库

1.历史背景 在Java Web项目中&#xff0c;常常使用免费开源的MySQL数据库存储业务数据&#xff0c;按业界经验MySQL单库超过多大数据体量&#xff0c;或单表超过几百万条数据后就会出现查询变慢的情况&#xff0c;单实例数据库只能扩展物理资源(CPU、内存)&#xff0c;来提升查…

【算法Hot100系列】搜索旋转排序数组

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

Postman工具使用一篇快速入门教程

文章目录 下载安装注册登录CollectionFolderRequestGet请求Post请求Header设置Response响应 EnvironmentsGlobal环境变量其他环境变量Collection变量变量使用同名变量的优先级 Postman内置变量Pre-request script和Test script脚本设置、删除和获取变量获取请求参数获取响应数据…

面试算法110:所有路径

题目 一个有向无环图由n个节点&#xff08;标号从0到n-1&#xff0c;n≥2&#xff09;组成&#xff0c;请找出从节点0到节点n-1的所有路径。图用一个数组graph表示&#xff0c;数组的graph[i]包含所有从节点i能直接到达的节点。例如&#xff0c;输入数组graph为[[1&#xff0c…

用可视化案例讲Rust编程2. 编码的核心组成:函数

从第一天学习编程&#xff0c;可能大家就听说这样的组成公式&#xff1a; 程序算法数据结构 ——该公式出自著名计算机科学家沃思(Nikiklaus Wirth) 实际上&#xff0c;程序除了以上两个主要要素之外&#xff0c;还应当采用结构化程序设计方法进行程序设计&#xff0c;并且用…

微信小程序实战-02翻页时钟-2

微信小程序实战系列 《微信小程序实战-01翻页时钟-1》 文章目录 微信小程序实战系列前言计时功能实现clock.wxmlclock.wxssclock.js 运行效果总结 前言 接着《微信小程序实战-01翻页时钟-1》&#xff0c;继续完成“6个页面的静态渲染和计时”功能。 计时功能实现 clock.wxm…

试问南昌大学——“荧”是怎么“赢”(大学生创新创业疑点案例3)

在第七届中国国际“互联网”大学生创新创业大赛上&#xff0c;南昌大学取得19金并斩获大赛冠军的佳绩&#xff01; 这期我们一起了解大赛金奖团队——南昌大学荧光微视项目团队的创新创业故事吧&#xff01; 回望整个比赛历程&#xff0c;团结协作一直是打开项目成功大门的金…

Helix QAC—软件静态测试工具

产品概述 Helix QAC是Perforce公司&#xff08;原PRQA公司&#xff09;产品&#xff0c;主要用于C/C代码的自动化静态分析工作&#xff0c;可以提供编码规则以及信息安全相关检查、代码质量度量、软件结构分析、测试结果管理等功能。Helix QAC能够准确地发现软件中潜在的问题&a…

UI自动化Selenium iframe切换多层嵌套

IFRAME是HTML标签&#xff0c;作用是文档中的文档&#xff0c;或者浮动的框架(FRAME)。iframe元素会创建包含另外一个文档的内联框架(即行内框架)。 简单来说&#xff0c;就像房子内的一个个房间一样&#xff1b;你要去房间里拿东西&#xff0c;就得先开门&#xff1b; 如上图…

语义解析:连接自然语言与机器智能的桥梁

文章目录 01 语义解析的应用场景场景一&#xff1a;场景二&#xff1a; 02 语义解析和大模型的关系 语义解析技术可以提高人机交互的效率和准确性&#xff0c;在自然语言处理、数据分析、智能客服、智能家居等领域都有广泛的应用前景。特别是在大数据时代&#xff0c;语义解析能…

Hotspot源码解析-第十七章-虚拟机万物创建(三)

17.4 Java堆空间内存分配 分配Java堆内存前&#xff0c;我们先通过两图来了解下C堆、Java堆、内核空间、native本地空间的关系。 1、从图17-1来看&#xff0c;Java堆的分配其实就是从Java进程运行时堆中选中一块内存区域来映射 2、从图17-2&#xff0c;可以看中各内存空间的…

03-Nacos微服务注册中心--快速入门

一、简介 Nacos&#xff08;Naming Configuration Service&#xff09; 是一个易于使用的动态服务发现、配置和服务管理平台&#xff0c;用于构建云原生应用程序 服务发现是微服务架构中的关键组件之一。Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用…

NOIP2012提高组day1-T3:开车旅行

题目链接 [NOIP2012 提高组] 开车旅行 题目描述 小 A \text{A} A 和小 B \text{B} B 决定利用假期外出旅行&#xff0c;他们将想去的城市从 1 1 1 到 n n n 编号&#xff0c;且编号较小的城市在编号较大的城市的西边&#xff0c;已知各个城市的海拔高度互不相同&#xf…

Word2Vec的CBOW模型

Word2Vec中的CBOW&#xff08;Continuous Bag of Words&#xff09;模型是一种用于学习词向量的神经网络模型。CBOW的核心思想是根据上下文中的周围单词来预测目标单词。 例如&#xff0c;对于句子“The cat climbed up the tree”&#xff0c;如果窗口大小为5&#xff0c;那么…

websocket: 了解并利用nodejs实现webSocket前后端通信

目录 第一章 前言 1.1 起源 1.2 短轮询与长轮询 1.2.1 短轮询 1.2.2 长轮询 1.2.3 长连接&#xff08;SSE&#xff09; 1.2.4 websocket 第二章 利用Node以及ws创建webSocket服务器 2.1 创建ws服务器&#xff08;后端部分&#xff09; 2.1.1 了解一下 2.1.2 代创建W…