【算法】双指针



快乐的流畅:个人主页


个人专栏:《算法神殿》《数据结构世界》《进击的C++》

远方有一堆篝火,在为久候之人燃烧!

文章目录

  • 一、移动零
  • 二、复写零
  • 三、快乐数
  • 四、盛最多水的容器
  • 五、有效三角形的个数
  • 六、和为s的两个数字
  • 七、三数之和
  • 八、四数之和
  • 总结

一、移动零


思路:

  1. 数组划分,快排核心步骤
  2. cur从头到尾扫描,prev划分非零与零元素的区间

时间复杂度:O(N)


class Solution
{
public:void moveZeroes(vector<int>& nums){//双指针算法,数组划分//快排数据划分核心思想int prev = -1, cur = 0;while(cur < nums.size()){if(nums[cur] && ++prev != cur)//避免原地交换{swap(nums[prev], nums[cur]);}++cur;}}
};

二、复写零


思路:

  1. 从前往后模拟,找到最后一个要复写的元素
  2. 处理越界情况
  3. 从后往前复写

时间复杂度:O(N)


class Solution
{
public:void duplicateZeros(vector<int>& arr){//1.找到最后一个要复写的元素int dest = -1, cur = 0;while(1){if(arr[cur]){dest++;}else{dest += 2;}if(dest >= arr.size()-1){break;}cur++;}//2.处理越界情况if(dest == arr.size()){//此时arr[cur]一定为0arr[dest-1] = 0;dest -= 2;cur--;}//3.从后向前复写while(cur >= 0){if(arr[cur]){arr[dest] = arr[cur];dest--;}else{arr[dest-1] = arr[dest] = 0;dest -= 2;}cur--;}}
};

三、快乐数


思路:

  1. 迭代过程中必有循环(鸽巢原理)
  2. 快慢指针,判断相遇的值是否为1

时间复杂度:O(logN)


class Solution
{
public:int Happy(int n){int sum = 0;while(n){sum += (n%10)*(n%10);n /= 10;}return sum;}bool isHappy(int n){//快慢双指针int slow = n, fast = n;do{slow = Happy(slow);fast = Happy(Happy(fast));}while(slow != fast);return slow == 1;}
};

四、盛最多水的容器


思路:

  1. 利用单调性,舍去短板组合的讨论
  2. 左右双指针

时间复杂度:O(N)


class Solution
{
public:int maxArea(vector<int>& height){//利用单调性,左右双指针int maxV = 0;int left = 0, right = height.size()-1;while(left < right){int tmpV = 0;if(height[left] < height[right]){tmpV = height[left] * (right-left);++left;}else{tmpV = height[right] * (right-left);--right;}maxV = tmpV > maxV ? tmpV : maxV;}return maxV;}
};

五、有效三角形的个数


思路:

  1. 先排序优化
  2. 再每次固定最大的数
  3. 利用单调性,左右指针

时间复杂度:O(N2)


class Solution
{
public:int triangleNumber(vector<int>& nums){//先进行排序优化sort(nums.begin(), nums.end());//再固定最大的数int cur = nums.size()-1;int num = 0;while(cur >= 2){//利用单调性,左右指针int left = 0, right = cur-1;while(left < right){if(nums[left] + nums[right] > nums[cur]){num += right-left;--right;}else{++left;}}--cur;}return num;}
};

六、和为s的两个数字


思路:利用单调性,左右指针

时间复杂度:O(N)


class Solution
{
public:vector<int> FindNumbersWithSum(vector<int> nums,int sum){int left = 0, right = nums.size()-1, flag = 0;while(left < right){if(nums[left] + nums[right] < sum){++left;}else if(nums[left] + nums[right] > sum){--right;}else{flag = 1;break;}}vector<int> v;if(flag){v.push_back(nums[left]);v.push_back(nums[right]);}return v;}
};

七、三数之和


思路:

  1. 先排序优化
  2. 再固定一个数(小优化:固定的数<=0即可)
  3. 双指针算法
  4. 注意不重不漏(这里的细节和快排相似):
    • 不漏:找到后,不要停,缩小空间继续找
    • 不重:遇到重复元素,不要停,继续缩小空间

时间复杂度:O(N2)


class Solution
{
public:vector<vector<int>> threeSum(vector<int>& nums){vector<vector<int>> vv;//先排序优化sort(nums.begin(), nums.end());//再固定一个数,利用双指针算法int cur = 0, n = nums.size();while(cur < n && nums[cur] <= 0)//固定的优化{int sum = -nums[cur];int left = cur+1, right = n-1;while(left < right){if(nums[left] + nums[right] < sum){++left;}else if(nums[left] + nums[right] > sum){--right;}else{vv.push_back({nums[cur], nums[left], nums[right]});//不漏:不要停,缩小区间继续找//不重:相同元素不要停,继续缩小区间int tmpL = nums[left], tmpR = nums[right];while(left < right && nums[left] == tmpL)//防止越界{++left;}while(left < right && nums[right] == tmpR)//防止越界{--right;}}}int tmpC = nums[cur];while(cur < n && nums[cur] == tmpC)//防止越界{++cur;}}return vv;}
};

八、四数之和


思路:与三数之和类似,多加上一个固定的数

时间复杂度:O(N3)


class Solution
{
public:vector<vector<int>> fourSum(vector<int>& nums, int target){vector<vector<int>> vv;//排序优化sort(nums.begin(), nums.end());//固定两个数,进行双指针算法int prev = 0, n = nums.size();while(prev < n){int cur = prev+1;while(cur < n){int left = cur+1, right = n-1;long long newTarget = (long long)target-nums[cur]-nums[prev];//防止数据溢出while(left < right){int sum = nums[left]+nums[right];if(sum < newTarget){++left;}else if(sum > newTarget){--right;}else{vv.push_back({nums[prev], nums[cur], nums[left], nums[right]});int tmpL = nums[left], tmpR = nums[right];while(left < right && nums[left] == tmpL){++left;}while(left < right && nums[right] == tmpR){--right;}}}int tmpC = nums[cur];while(cur < n && nums[cur] == tmpC){++cur;}}int tmpP = nums[prev];while(prev < n && nums[prev] == tmpP){++prev;}}return vv;}
};

总结

双指针算法,是一种极高效的优化算法,可以将时间复杂度优化一个级别(比二分更加高效),比如O(N3 )变成O(N2),O(N2 )变成O(N),O(N)变成O(1)……

双指针算法,主要分为前后指针,快慢指针,左右指针

  • 前后指针,主要运用于处理数据,包括移动和修改
  • 快慢指针,主要运用于链表或者类似链表中存在环时,寻找数据
  • 左右指针,主要运用于数据有序,或者具有某种单调性时,寻找数据

真诚点赞,手有余香

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

囊括所有大模型:高质量中文预训练模型大模型多模态模型大语言模型集合

在自然语言处理领域中&#xff0c;预训练语言模型&#xff08;Pretrained Language Models&#xff09;已成为非常重要的基础技术&#xff0c;本仓库主要收集目前网上公开的一些高质量中文预训练模型、中文多模态模型、中文大语言模型等内容(感谢分享资源的大佬)&#xff0c;并…

Intel Arc显卡安装Stable Diffusion

StableDiffusion是一种基于深度学习的文本到图像生成模型&#xff0c;于2022年发布。它主要用于根据文本描述生成详细图像&#xff0c;也可应用于其他任务&#xff0c;如内补绘制、外补绘制和在提示词指导下生成图像翻译。通过给定文本提示词&#xff0c;该模型会输出一张匹配提…

13-API风格(下):RPCAPI介绍

RPC在Go项目开发中用得也非常多&#xff0c;需要我们认真掌握。 RPC介绍 根据维基百科的定义&#xff0c;RPC&#xff08;Remote Procedure Call&#xff09;&#xff0c;即远程过程调用&#xff0c;是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一台计算机…

Java项目实战笔记--基于SpringBoot3.0开发仿12306高并发售票系统--(二)项目实现-第五篇-核心功能车票预定开发及nacos集成

本文参考自 Springboot3微服务实战12306高性能售票系统 - 慕课网 (imooc.com) 本文是仿12306项目实战第&#xff08;二&#xff09;章——项目实现 的第五篇&#xff0c;本篇讲解该项目的核心功能——余票查询、车票预定功能的基础版开发&#xff0c;以及讲解项目与Nacos的集成…

【保姆级】2024年最新Onlyfans使用订阅教程

【必看】开通步骤 订阅OnlyFans的步骤简要总结如下&#xff1a; 开通虚拟信用卡&#xff1a;虚拟信用卡开通使用教程。开卡后&#xff0c;进入首页&#xff0c;就能看到自己的虚拟信用卡信息把虚拟信用卡的信息填写到OnlyFans绑定信用卡界面就OK了 从上面的链接进入开卡费可…

考研数学|《1800》+《660》精华搭配混合用(经验分享)

肯定不行&#xff0c;考研数学哪有这么容易的&#xff01; 先说说这两本习题册&#xff0c;李永乐老师推出的新版660题&#xff0c;相较于18年前的版本&#xff0c;难度略有降低&#xff0c;更加适合初学者。因此&#xff0c;对于处于基础阶段的学习者来说&#xff0c;新版660…

GeoTrust SSL证书有什么优势?

GeoTrust SSL证书具备以下显著优势&#xff1a; 1. 市场占有率比较高&#xff1a;GeoTrust作为知名的SSL证书供应商&#xff0c;拥有广泛的市场接受度和高占有率&#xff0c;表明其产品受到众多企业和网站的信任和采用。 2. 品牌信誉与信任标识&#xff1a;在高安全性浏览器中&…

React Native框架开发APP,安装免费的图标库(react-native-vector-icons)并使用详解

一、安装图标库 要使用免费的图标库&#xff0c;你可以使用 React Native Vector Icons 库。 首先&#xff0c;确保你已经安装了 react-native-vector-icons&#xff1a; npm install --save react-native-vector-iconsnpm install --save-dev types/react-native-vector-ic…

深度思考:雪花算法snowflake分布式id生成原理详解

雪花算法snowflake是一种优秀的分布式ID生成方案&#xff0c;其优点突出&#xff1a;它能生成全局唯一且递增的ID&#xff0c;确保了数据的一致性和准确性&#xff1b;同时&#xff0c;该算法灵活性强&#xff0c;可自定义各部分bit位&#xff0c;满足不同业务场景的需求&#…

谷粒商城实战(007 压力测试)

Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强 总时长 104:45:00 共408P 此文章包含第141p-第p150的内容 简介 安装jmeter 安装jmeter 使用中文 这样写就是200个线程循环100次 一共是2万个请求 介绍线程组 添加请求 可以是htt…

【物联网】Qinghub opc-ua 连接协议

基础信息 组件名称 &#xff1a; opcua-connector 组件版本&#xff1a; 1.0.0 组件类型&#xff1a; 系统默认 状 态&#xff1a; 正式发布 组件描述&#xff1a;通过OPCUA连接网关&#xff0c;通过定时任务获取OPCUA相关的数据或通过执行指令控制设备相关参数。 配置文件&a…

软件设计不是CRUD(16):低耦合模块设计理论——行为抽象与设计模式(下)

(接上文《软件设计不是CRUD(15):低耦合模块设计理论——行为抽象与设计模式(中)》) 3.2.4、之前的业务逻辑需要关注后续逻辑的执行成败,并调整自身执行的情况 这个场景在之前场景的基础上增加了新的控制要求,具体来说就是之前已经完成的控制逻辑执行,需要在后续控制…