C/C++算法-----------------------双指针详解技巧及例题

双指针

  • 基本介绍
  • 降低时间复杂度
    • 降低时间复杂度例题
  • 验证回文串
  • 判断是否为环
  • 反转链表
  • 总结

基本介绍

双指针(two poinnters)实际上是一种算法编程里的一种思想,它更像是一种编程思想,提供看非常高的算法效率,一般来说双指针指的是在遍历对象时使用两个或多个指针遍历进行操作,经常可以用来降低时间复杂度,那么双指针主要分为以下三种:

普通的指针:两个指针往一个方向移动
对撞指针:一般是在有序的情况下两个指针进行面对面的移动,适合解决约束条件的一组元素问题以及字符串反转问题
快慢指针:定义两个指针,一个快指针一个慢指针,用于判断是否为环或者长度的问题很方便

降低时间复杂度

假设我们有一个二维数组arr,大小为n x m,我们要对其进行双层循环遍历,原代码如下:

for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {// 执行操作}
}

我们使用双指针优化这个循环。首先,我们定义两个指针p1和p2,初始时分别指向数组的第一个元素。然后,我们使用一个循环来遍历数组,每次迭代更新指针的位置,并执行操作

int p1 = 0; // 第一个指针初始位置
int p2 = 0; // 第二个指针初始位置while (p1 < n && p2 < m) {// 执行操作// 更新指针的位置p2++;if (p2 == m) {p2 = 0;p1++;}
}

这个例子将时间复杂度从O(n^2)降低到了O(n),需要注意的是,双指针优化适用于一些特定情况,例如对称矩阵、上三角矩阵或者二维数组中的某种特定模式,在其他情况下,双指针可能并不适用或者无法有效地优化时间复杂度,因此,在具体问题中,需要根据实际情况判断是否可以使用双指针优化,接下来看一个降低时间复杂度的例题:

降低时间复杂度例题

给定一个有序的递增数组,数组arr={1,3,4,9,11,12,14},找到两个数之和为12,找到一组即可停止
思路:这题最容易想到的就是暴力算法,即直接两层循环嵌套逐个查找,但时间复杂度为:O(n^2)
暴力算法:

for(int i=0;i<n;i++){for(int j=0;j<n;j++){if(arr[i]+arr[j]==k)cout<<arr[i]<<arr[j]>>endl;}
}

双指针:这题使用双指针大大降低了时间复杂度

	int i = 0; // 从头开始的索引int j = arr.size() - 1; // 从尾开始的索引while (i < j)
{if (arr[i] + arr[j] < k){i++; // 如果arr[i]和arr[j]的和小于k,则增加i的值}else if (arr[i] + arr[j] > k){j--; // 如果arr[i]和arr[j]的和大于k,则减小j的值}else{cout << arr[i] << arr[j] << endl; // 如果arr[i]和arr[j]的和等于k,则输出这两个数并结束循环break;}
}return 0;

验证回文串

回文串:是指正向读和反向读都相同的字符串
很经典的题目,用双指针更能事半功倍,这里使用了对撞指针,即两个指针不断往中间靠拢,并对比是否相等,如果相等并且比较完了则代表是回文串

bool isPalindrome(string s) {// 定义左右指针int left = 0;int right = s.length() - 1;// 循环进行比较,直到两个指针相遇while (left < right) {// 跳过非字母和数字字符,只比较字母和数字字符if (!isalnum(s[left])) {left++;continue;}if (!isalnum(s[right])) {right--;continue;}// 将字符转换为小写比较if (tolower(s[left]) != tolower(s[right])) {return false; // 不是回文串,直接返回false}// 移动指针继续比较下一对字符left++;right--;}return true; // 是回文串,返回true
}

判断是否为环

力扣第LeetCode第141.环形链表:https://leetcode.cn/problems/linked-list-cycle/description/
给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false
示例 1:
在这里插入图片描述

class Solution {
public:bool hasCycle(ListNode *head) {// 检查链表是否为空,如果为空则返回 falseif (head == NULL)return false;// 初始化慢指针和快指针,开始位置都是头节点的位置ListNode* solt = head;ListNode* fast = head->next;// 循环遍历链表,直到慢指针和快指针相遇或者快指针到达链表末尾while (solt != fast) {// 如果快指针到达链表末尾或者倒数第二个节点,则表示链表没有环,返回 falseif (fast == NULL || fast->next == NULL)return false; // 更新慢指针和快指针的位置solt = solt->next;fast = fast->next->next;}// 如果循环结束后慢指针和快指针相遇,则表示链表有环,返回 truereturn true;}
};

对于上诉的问题我们可以使用双指针中的快慢指针来判断是否为环,定义一个一次走一步的指针solt和一次走两步的指针fast,从起点开始如果存在为环的话fast指针一定能追上solt即再次相遇,若相遇了则代表为环,快慢指针对于判断是否为环的情况下效率很高

反转链表

力扣LCR. 024.反转链表:https://leetcode.cn/problems/UHnkqh/description/
给定单链表的头节点 head ,请反转链表,并返回反转后的链表的头节点。
在这里插入图片描述

class Solution {
public:ListNode* reverseList(ListNode* head) {// 如果链表为空或者只有一个节点,直接返回head(因为不需要反转)if (!head || !head->next) {return head;}ListNode* prev = nullptr;  // 用于存储当前节点的前一个节点ListNode* curr = head;      // 当前节点while (curr) {ListNode* nextNode = curr->next;  // 临时保存下一个节点的指针curr->next = prev;                // 反转指针,将当前节点指向前一个节点prev = curr;                      // 更新prev指针为当前节点curr = nextNode;                  // 更新curr指针为下一个节点}return prev;  // 返回反转后的头节点}
};

这道题使用了双指针:
prev指针用于存储当前节点的前一个节点,在代码中初始化为nullptr,表示当前节点没有前一个节点。
1.curr指针用于遍历链表,初始时指向头节点。
2.在循环中,首先将curr的下一个节点保存到临时变量nextNode中,以便后续使用。
3.接着将curr的next指针指向prev,实现了指针的反转。
4.然后更新prev为curr,将curr指针移动到下一个节点nextNode。
重复上述步骤直至遍历完整个链表。

总结

以上就是关于双指针的案例及分析,双指针并不是一种数据结构而是一种很经典的算法思想,可以通过它解决很多问题,其核心思想是设计一个不同速度、不同间距、及不同方向的两个指针来解决问题,在具体问题中,需要根据实际情况判断是否可以使用双指针,最重要的还是多刷题

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

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

相关文章

Pytorch D2L Subplots方法对画图、图片处理

问题代码 def show_images(imgs, num_rows, num_cols, titlesNone, scale1.5): #save """绘制图像列表""" figsize (num_cols * scale, num_rows * scale) _, axes d2l.plt.subplots(num_rows, num_cols, figsizefigsize) axes axes.flatten…

WebGoat通关攻略之 SQL Injection (intro)

SQL Injection (intro) 1. What is SQL? 本题练习SQL查询语句&#xff0c;就是写一句SQL获取叫Bob Franco所在的department SELECT department FROM employees WHERE first_name Bob AND last_name Franco成功通关&#xff01; 2. Data Manipulation Language (DML) 本题…

PS 吸管工具基本使用方法

这里 我们先打开PS软件 我们 在左侧 导航来中 找到 有吸管工具的这一组工具 这边 我们先选择这个 吸管工具 选择之后呢 左上角 属性配置 第一个是 取样大小 这个 我们之前学魔棒工具时 是有接触过的 这里 我们选择 取样点 然后 后面一个是样本 这个 用的最多的是 所有图层 …

猫罐头哪个牌子好?分享十款猫罐头品牌排行榜!

选择适合的猫罐头非常重要&#xff0c;好的猫罐头应该提供丰富的营养、适量的水分、口感良好&#xff0c;并且易于消化吸收。然而&#xff0c;如果选择不当&#xff0c;可能无法达到期望的效果&#xff0c;甚至可能对猫咪产生负面影响。 作为一位经营猫咖5年的老板&#xff0c;…

Flink(六)【DataFrame 转换算子(下)】

前言 今天学习剩下的转换算子。 1、物理分区算子 常见的物理分区策略有随机分配&#xff08;Random&#xff09;、轮询分配&#xff08;Round-Robin&#xff09;、重缩放&#xff08;Rescale&#xff09;和广播&#xff08;Broadcast&#xff09;&#xff0c;下边我们分别来做…

IDEA远程一键部署SpringBoot到Docker

IDEA是Java开发利器&#xff0c;Spring Boot是Java生态中最流行的微服务框架&#xff0c;docker是时下最火的容器技术&#xff0c;那么它们结合在一起会产生什么化学反应呢&#xff1f; 一、开发前准备 1. Docker安装 可以参考&#xff1a;https://docs.docker.com/install/ 2…

【Vue全家桶 合集 关注收藏】

【Vue全家桶】全面了解学习并实践总结Vue必备知识点 写在前面 &#x1f917; 这里是SuperYi Vue全家桶合集站&#xff01; &#x1f33b; 人海茫茫&#xff0c;感谢这一秒你看到这里。希望我的文章对你的有所帮助&#xff01; &#x1f31f; 愿你在未来的日子&#xff0c;保持…

CentOs 7 PHP安装和配置

目录 1 安装epel源 2 安装REMI源 3 安装yum源管理工具 4 安装PHP7.3 5 启动php服务 6 设置PHP 6.1 查找安装包 6.2 查找PHP安装位置 6.3 查找php配置文件位置 6.4 配置PHP 6.5 设置快捷命令 6.6 查看php版本 6.7 更新php 1 安装epel源 yum -y install epel-release 2 安…

【Python基础篇】字符串的拼接

博主&#xff1a;&#x1f44d;不许代码码上红 欢迎&#xff1a;&#x1f40b;点赞、收藏、关注、评论。 格言&#xff1a; 大鹏一日同风起&#xff0c;扶摇直上九万里。 文章目录 一 Python中的字符串拼接二 join函数拼接三 os.path.join函数拼接四 号拼接五 &#xff0c;号…

招聘全球视野:跨境电商的人才策略

在数字时代&#xff0c;跨境电商已经成为全球商业领域的引擎之一。由于全球市场的巨大潜力&#xff0c;跨境电商企业需要确保其人才团队具备全球视野和战略洞察力&#xff0c;以在竞争激烈的环境中脱颖而出。本文将深入探讨招聘全球视野的重要性&#xff0c;并提供一些战略性的…

jupyter修改默认打开目录

当我们打开jupyter notebook&#xff08;不管用什么样的方式打开&#xff0c;使用菜单打开或者是命令行打开是一样的&#xff09;会在默认的浏览器中看到这样的界面、 但是每一台不同的电脑打开之后的界面是不同的&#xff0c;仔细观察就会发现&#xff0c;这里面现实的一些文件…

新的 Reptar CPU 缺陷影响英特尔台式机和服务器系统

英特尔修复了其现代台式机、服务器、移动和嵌入式 CPU 中的一个高严重性 CPU 漏洞&#xff0c;包括最新的 Alder Lake、Raptor Lake 和 Sapphire Rapids 微架构。 攻击者可以利用该缺陷&#xff08;追踪为CVE-2023-23583并被描述为“冗余前缀问题”&#xff09;来升级权限、获…