【C++算法】双指针

目录

一、快乐数:

二、有效三角形的个数:

三、盛最多水的容器:

四、复写0:

五、三数之和:

总结:


一、快乐数:

题目出处:

202. 快乐数 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/happy-number/

题目说明:

输入示例:

如上图所示:

当输入一个数字的时候,经过多次变化,一定会进入一个圆,如果最后是1可以看做一个圆,里面都是1。如果不是1,那么一定会进入一个圆里面。那么会不会出现一个无限不循环的呢?答案是不会的。

证明思路:

首先,正整型最大的是2147483647,那么便于计算将9999999999代替它,那么将9999999999经过题目所给的方式计算后的结果为810,所以经过题目的操作后,其结果肯定在0~810中,所以一个数字经过811次题目所给操作后肯定会有重复的,那么就会进入一个圆

解题思路:

首先定义快慢指针,慢指针指向输入的数,快指针指向进行一次题目操作后的数字,

因为要多次进行题目所给的操作,所以就需要将题目所给操作封装成一个函数,

最后使用循环判断知直到二者相遇就结束循环,最后返回二者之一是否等于1即可

class Solution {
public:
    int func(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 = func(n);
        while(slow != fast)
        {
            slow = func(slow);
            fast = func(func(fast));
        }
        return slow == 1;
    }
};

二、有效三角形的个数:

题目出处:

611. 有效三角形的个数 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/valid-triangle-number/题目说明:

输入示例:

解题思路:

既然可以包含重复的,那么就不需要进行去重操作。

主要思路是暴力解法(将每一个情况都列举出来,之后通过三角形两边之和大于另一边进行判断),双指针在暴力解法上更加快速:(三角形最短两边之和大于最长的一边)

那么就将整个数组进行排序(因为这样的话就方便使用双指针进行操作)

需要三个变量,一个指向最左边作为短边,一个指向最右边作为最长的一边,另一个在中间的区间进行寻找能够构成三角形的三个数字。

其中两个if判断

一个if

如果最左边left和最右边right所在的值相加比第三边都长的话就证明左边的所有和right相加都比第三边大,这个时候直接进行right-left找到所有情况加到ret返回值即可,

另一个if就是左边最小的值和右边最大的值相加都小于等于最大的max,这样的话就证明left和右边所有相加都不能够构成三角形,left继续++即可

class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int ret = 0;
        int left = 0,right = nums.size()-2,max = nums.size()-1;
        while(max>left)
        {
            while(left < right)
            {
                if(nums[left]+nums[right] > nums[max])
                {
                    ret += right-left;
                    right--;
                }
                else//nums[left]+nums[right] <= nums[max]
                {
                    left++;
                }
            }
            max--;
            left = 0;
            right = max-1;
        }
        return ret;
    }
};

三、盛最多水的容器:

题目出处:

11. 盛最多水的容器 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/container-with-most-water/题目说明:

示例:

解题思路:

首先依然是双指针就定义left和right指针指向最左和最右,这里还需要宽度(right-left),高度(left和right所对应的值中小的那一个)最大体积,当前体积(如果比最大体积大就更新最大体积)

之后在循环中使用双指针,

if语句中

如果此时left所在的高度比right所在的高度小,那么就证明left~right中间的所有和此时的left组合成的容器所盛水的体积都比此时要小

所以就将left++;

如果此时left所在的高度比right所在的高度大,那么就证明left~right中间的所有和此时的right组合成的容器所盛水的体积都比此时要小

所以就将right--;

最后更新宽度,高度,此时体积和max体积比较。

循环结束后返回max体积即可

class Solution {
public:
    int maxArea(vector<int>& height) {
        int left = 0;
        int right = height.size() - 1;
        int wide = right - left;
        int high = height[left] < height[right] ? height[left] : height[right];
        int tempval = 0;
        int maxval = wide*high; 
        while(left < right)
        {
            if(height[left]<height[right])
            {
                left++;
            }
            else
            {
                right--;
            }
            wide--;
            high = height[left] < height[right] ? height[left] : height[right];
            tempval = wide*high;
            if(tempval > maxval)
            {
                maxval = tempval;
            }
        }
        return maxval;
    }
};

四、复写0:

题目出处:

1089. 复写零 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/duplicate-zeros/题目说明:

解题思路:

首先对于arr数组,复写0,如果从前往后进行复写的时候会发现无论怎样都会覆盖某些值,这样就会丢失数据,那么就需要从后往前进行复写操作。

那么既然是复写,并且数组元素确定,那么肯定这个数组中存在一个数(这个数可能是中间的某个,也可能是最后一个),在进行复写操作后就变为新数组的最后一个数,那么就需要在复写之前找到这个数。 

找到这个数之后就可以进行复写了。

找这个数的思路:

首先依然是定义两个“指针”,一个在数组0位置,另一个在数组-1位置(但是这个位置不会访问,也不能访问)接着往后进行遍历,一般情况下cur在dest的下一个,但是如果cur的位置不是0的话,两个都++,如果cur位置是0的话,就将dest向右移动两位,如果dest到最后的时候,此时cur位置就是要找的这个值。

但是有一个例外情况,就是dest最后+2后越界访问了,这样的话就在确定cur后进行边界检查

最后复写即可:

如果cur位置不是0就直接和dest交换,之后将二者向左移一个位置

如果cur位置是0就将cur和dest交换,之后将二者向左移一个位置,在将此时的dest修改为0,在将dest向左移一个位置。

class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        int cur = 0;
        int dest = -1;
        int n = arr.size();
        while(dest < n - 1)
        {
            //如果cur位置是0,dest就走两步,不是0就走一步
            if(arr[cur])
            {
                dest++;
            }
            else
            {
                dest += 2;
            }
            if(dest >= n - 1)
                break;
            cur++;
        }
        if(dest == n)
        {
            arr[n-1] = 0;
            cur--;
            dest-=2;
        }
        while(cur>=0)
        {
            if(arr[cur])
            {
                swap(arr[cur--],arr[dest--]);
            }
            else
            {
                swap(arr[cur--],arr[dest--]);
                arr[dest--] = 0;
            }
        }
    }
};

五、三数之和:

题目出处:

15. 三数之和 - 力扣(LeetCode)icon-default.png?t=O83Ahttps://leetcode.cn/problems/3sum/description/题目说明:

解题思路:

思路一:

首先进行排序,在进行暴力枚举,最后再利用容器去重

上述方法由于是暴力枚举,在本题中会超时

思路二(“双指针”法):

1、首先依然是进行排序,

2、然后分析题目,要找到三个数相加为0,其实也可以看做两个数的和等于第三个数的相反数。

3、那么就可以首先固定一个数为目标数记为ret,在这个数的后面寻找其余两个数,这两个数的和是-ret即可

注意细节:

1、题目说不能有重复的三元组,那么就需要去重操作。

去重思路:

a、容器去重,直接利用set或者unordered_set进行去重处理

b、每次找到一种结果之后将left和right指针跳过重复元素,当使用完一次双指针之后,也就是在一个ret找完后,ret也要跳过重复元素。

2、要保证不能漏

不漏比较好处理,只需要在每次找到一种结果之后,继续走完当前情况

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        vector<vector<int>> v;
        int i = 0,n = nums.size();
        int ret = 0;
        while(i<n)
        {
            ret = nums[i];
            int left = i+1,right = n-1;
            while(left < right)
            {
                int sum = -(nums[left] + nums[right]);
                //-4 -3 -2 -1 0 1 2 3 4 5 6 7 8
                if(ret < sum) ++left;
                else if(ret > sum) --right;
                else
                {
                    v.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<n && nums[i] == nums[i-1]) i++;
        }
        return v;
    }
};

总结:

双指针算法适用于一串有序的数字,能够将暴力枚举的时间复杂度降低一维,n^3->n^2

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

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

相关文章

ROS2 通信三大件之动作 -- Action

通信最后一个&#xff0c;也是不太容易理解的方式action&#xff0c;复杂且重要 1、创建action数据结构 创建工作空间和模块就不多说了 在模块 src/action_moudle/action/Counter.action 下创建文件 Counter.action int32 target # Goal: 目标 --- int32 current_value…

智能健康顾问:基于SpringBoot的系统

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

Qt:图片文字转base64程序

目录 一.Base64 1.编码原理 2.应用场景 3.优点 4.限制 5.变种 二.文字与Base64互转 1.ui设计 2.文字转Base64 3.Base64转文字 三.图片与Base64互转 1.ui设计 2.选择图片与图片路径 3.图片转Base64 4.Base64转图片 四.清空设置 五.效果 六.代码 base64conver…

PDF编辑不求人!4款高效工具,内容修改从此变得简单又快捷

咱们现在生活在一个数字时代&#xff0c;PDF文件可不就是工作、学习还有日常生活中经常要用的东西嘛。但遇到那些需要改动的PDF文件&#xff0c;是不是就觉得有点头疼啊&#xff1f; 因为传统的PDF文件真的不好编辑&#xff0c;这确实挺烦人的。不过呢&#xff0c;我今天要给你…

【北京迅为】《STM32MP157开发板嵌入式开发指南》- 第三十九章 Linux Misc驱动

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…

SpringBoot下的智能健康推荐引擎

3系统分析 3.1可行性分析 通过对本基于智能推荐的卫生健康系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本基于智能推荐的卫生健康系统采用SSM框架&#…

24秋面试笔记

文章目录 一、专业技能1.1 具备扎实的Java基础&#xff0c;熟练掌握面向对象编码规范、集合、反射以及Java8特性等。1.1.1 Java基础1.1.2 集合1.1.3 Java8新特性 1.2 熟悉常用的数据结构(链表、栈、队列、二叉树等)&#xff0c;熟练使用排序、动态规划、DPS等算法。1.2.1 数据结…

CountUp.js 实现数字增长动画 Vue

效果&#xff1a; 官网介绍 1. 安装 npm install --save countup.js2. 基本使用 // template <span ref"number1Ref"></span>// script const number1Ref ref<HTMLElement>() onMounted(() > {new CountUp(number1Ref.value!, 9999999).sta…

Centos7 搭建单机elasticsearch

以下是在 CentOS 7 上安装 Elasticsearch 7.17.7 的完整步骤&#xff1a;&#xff08;数据默认保存在/var/lib/elasticsearch下&#xff0c;自行更改&#xff09; 一、装 Java 环境 Elasticsearch 是用 Java 编写的&#xff0c;所以需要先安装 Java 运行环境。 检查系统中是…

弘景光电:以创新为翼,翱翔光学科技新蓝海

在科技日新月异的今天&#xff0c;光学镜头及模组作为智能设备的核心组件&#xff0c;其重要性日益凸显。广东弘景光电科技股份有限公司&#xff08;以下简称“弘景光电”&#xff09;正是在这一领域中&#xff0c;凭借其卓越的研发实力和市场洞察力&#xff0c;即将在创业板上…

001 Qt_从零开始创建项目

文章目录 前言什么是QtQt的优点Qt的应用场景创建项目小结 前言 本文是Qt专栏的第一篇文章&#xff0c;该文将会向你介绍如何创建一个Qt项目 什么是Qt Qt 是⼀个 跨平台的 C 图形⽤⼾界⾯应⽤程序框架 。它为应⽤程序开发者提供了建⽴艺术级图形界⾯所需的所有功能。它是完全…

英特尔新旗舰 CPU 将运行更凉爽、更高效,适合 PC 游戏

英特尔终于解决了台式机 CPU 发热和耗电的问题。英特尔的新旗舰 Core Ultra 200S 系列处理器将于 10 月 24 日上市&#xff0c;该系列专注于每瓦性能&#xff0c;比之前的第 14 代芯片运行更凉爽、更高效。这些代号为 Arrow Lake S 的处理器也是英特尔首款内置 NPU&#xff08;…

Unity3D 观察者模式

Unity3D 泛型事件系统 观察者模式 观察者模式是一种行为设计模式&#xff0c;通过订阅机制&#xff0c;可以让对象触发事件时&#xff0c;通知多个其他对象。 在游戏逻辑中&#xff0c;UI 界面通常会监听一些事件&#xff0c;当数据层发生变化时&#xff0c;通过触发事件&am…

LabVIEW提高开发效率技巧----状态保存与恢复

在LabVIEW开发中&#xff0c;保存和恢复程序运行时的状态是一个关键技巧&#xff0c;特别是在涉及需要暂停或恢复操作的应用中。通过使用 Flatten To String 和 Unflatten From String 函数&#xff0c;开发人员可以将程序当前的状态转换为字符串并保存&#xff0c;再在需要时恢…

决策树随机森林-笔记

决策树 1. 什么是决策树&#xff1f; 决策树是一种基于树结构的监督学习算法&#xff0c;适用于分类和回归任务。 根据数据集构建一棵树&#xff08;二叉树或多叉树&#xff09;。 先选哪个属性作为向下分裂的依据&#xff08;越接近根节点越关键&#xff09;&#xff1f;…

人工智能和机器学习之线性代数(一)

人工智能和机器学习之线性代数&#xff08;一&#xff09; 人工智能和机器学习之线性代数一将介绍向量和矩阵的基础知识以及开源的机器学习框架PyTorch。 文章目录 人工智能和机器学习之线性代数&#xff08;一&#xff09;基本定义标量&#xff08;Scalar&#xff09;向量&a…

机器视觉AI场景为什么用Python比C++多?

好多开发者在讨论机在机器视觉人工智能领域的时候&#xff0c;纠结到底是用Python还是C&#xff0c;实际上&#xff0c;Python 和 C 都有广泛的应用&#xff0c;选择 Python而不是 C 可能有以下一些原因&#xff1a; 语言易学性和开发效率 语法简洁&#xff1a; Python 语法简…

软考系统分析师知识点十:软件工程

前言 今年报考了11月份的软考高级&#xff1a;系统分析师。 考试时间为&#xff1a;11月9日。 倒计时&#xff1a;27天。 目标&#xff1a;优先应试&#xff0c;其次学习&#xff0c;再次实践。 复习计划第一阶段&#xff1a;扫平基础知识点&#xff0c;仅抽取有用信息&am…

【消息队列】Kafka从入门到面试学习总结

国科大学习生活&#xff08;期末复习资料、课程大作业解析、大厂实习经验心得等&#xff09;: 文章专栏&#xff08;点击跳转&#xff09; 大数据开发学习文档&#xff08;分布式文件系统的实现&#xff0c;大数据生态圈学习文档等&#xff09;: 文章专栏&#xff08;点击跳转&…

【C】C语言常见概念~

C语言常见概念 转义字符 转义字符&#xff0c;顾名思义&#xff0c;转变原来意思的字符 比如 #include <stdio.h> int main() {printf("abcndef");return 0; }输出的结果为&#xff1a; 将代码修改一下&#xff1a; #include <stdio.h> int main(…