C++刷题 -- 链表

C++刷题 – 链表

文章目录

  • C++刷题 -- 链表
    • 1.删除链表的倒数第 N 个结点
    • 2.链表相交
    • 3.环形链表


1.删除链表的倒数第 N 个结点

https://leetcode.cn/problems/remove-nth-node-from-end-of-list/

快慢指针的应用

  • fast指针先移动N步,slow依然指向head;
  • 然后fast和slow同时移动,直到fast指向链表最后一个节点的next,也就是空,此时slow就指向了倒数第N个节点;
/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* removeNthFromEnd(ListNode* head, int n) {if(head == nullptr || head->next == nullptr){return nullptr;}ListNode* fast = head;ListNode* slow = head;ListNode* prev = nullptr;//fast指针先移动N步,slow依然指向headfor(int i = 0; i < n; i++){fast = fast->next;}//然后fast和slow同时移动,直到fast指向链表最后一个节点的next,也就是空,此时slow就指向了倒数第N个节点while(fast){fast = fast->next;prev = slow;slow = slow->next;}if(prev) {prev->next = slow->next;delete(slow);}else // 如果prev为空,则删除的是头结点{prev = head;head = head->next;delete(prev);}return head;}
};

2.链表相交

https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/description/

  • 两个链表相交之后的部分一定是相同的;
  • 可以分别计算两个链表的长度,然后计算长度差
  • 让两个链表从末尾对齐,如下图所示,指针curA和curB同时向后遍历,直到两者的指针地址相同;
    请添加图片描述
/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {int cntA = 0, cntB = 0;ListNode* curA = headA;ListNode* curB = headB;//遍历得到AB的长度while(curA){cntA++;curA = curA->next;}while(curB){cntB++;curB = curB->next;}//计算长度差,让长链表先走int skip = abs(cntA - cntB);ListNode* longerList = headA;ListNode* shorterList = headB;if(cntA < cntB){swap(longerList, shorterList);}curA = longerList;curB = shorterList;while(skip--){curA = curA->next;}//两个指针一起走while(curA != curB){curA = curA->next;curB = curB->next;}return curA;}
};

3.环形链表

https://leetcode.cn/problems/linked-list-cycle-ii/description/

判断链表是否有环

  • 快慢指针:分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环
  • fast指针一定先进入环中,如果fast指针和slow指针相遇的话,一定是在环中相遇;
  • 这是因为fast是走两步,slow是走一步,其实相对于slow来说,fast是一个节点一个节点的靠近slow的,所以fast一定可以和slow重合请添加图片描述

找到这个环的入口

  • 假设从头结点到环形入口节点 的节点数为x。 环形入口节点到 fast指针与slow指针相遇节点 节点数为y。 从相遇节点 再到环形入口节点节点数为 z。请添加图片描述
    -那么相遇时: slow指针走过的节点数为: x + y, fast指针走过的节点数:x + y + n (y + z),n为fast指针在环内走了n圈才遇到slow指针, (y+z)为 一圈内节点的个数A。
  • 因为fast指针是一步走两个节点,slow指针一步走一个节点, 所以 fast指针走过的节点数 = slow指针走过的节点数 * 2
    (x + y) * 2 = x + y + n (y + z)
  • 两边消掉一个(x+y): x + y = n (y + z)
  • 因为要找环形的入口,那么要求的是x,因为x表示 头结点到 环形入口节点的的距离。
  • 将x单独放在左面:x = n (y + z) - y
  • 再从n(y+z)中提出一个 (y+z)来,整理公式之后为如下公式:x = (n - 1) (y + z) + z 注意这里n一定是大于等于1的,因为 fast指针至少要多走一圈才能相遇slow指针
  • 先拿n为1的情况来举例,意味着fast指针在环形里转了一圈之后,就遇到了 slow指针了。
    当 n为1的时候,公式就化解为 x = z
  • 这就意味着,从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点。
  • 也就是在相遇节点处,定义一个指针index1,在头结点处定一个指针index2。
    让index1和index2同时移动,每次移动一个节点, 那么他们相遇的地方就是 环形入口的节点。请添加图片描述
  • 那么 n如果大于1是什么情况呢,就是fast指针在环形转n圈之后才遇到 slow指针。
    其实这种情况和n为1的时候 效果是一样的,一样可以通过这个方法找到 环形的入口节点,只不过,index1 指针在环里 多转了(n-1)圈,然后再遇到index2,相遇点依然是环形的入口节点。
/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode *detectCycle(ListNode *head) {ListNode* fast = head;ListNode* slow = head;while(fast && fast->next) //如果没有环,fast或者fast->next就会为空{fast = fast->next->next; //快指针一次走两步slow = slow->next; //慢指针一次走一步//若有环,则fast和slow会在环内相遇if(fast == slow){//两个指针从相遇节点和头节点同时向后走,最终的相遇点就是环的入口ListNode* index1 = head;ListNode* index2 = fast;while(index1 != index2){index1 = index1->next;index2 = index2->next;}return index2;}}return nullptr;}
};

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

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

相关文章

Halcon threshold_sub_pix (Operator)

read_image(Image,fabrik) threshold_sub_pix(Image,Border,35) dev_display(Border)Image是输入的原始图像&#xff0c;Threshold是设定的阈值&#xff0c;Width和Height是像素值计算区域的大小&#xff0c;ThresholdedRegion是经过分割后得到的二值化结果。 在对图像进行二值…

Docker-compose容器编排与容器监控

一、Docker-compose 1、概念&#xff1a; Docker-Compose 是 Docker 官方的开源项目&#xff0c;负责实现对Docker容器集群的快速编排。 2、作用&#xff1a; Docker-Compose可以管理多个Docker容器组成一个应用。需要定义一个yaml格式的配置文件 docker-compose.yml&#…

PostGIS学习教程十一:投影数据

PostGIS学习教程十一&#xff1a;投影数据 地球不是平的&#xff0c;也没有简单的方法把它放在一张平面纸地图上&#xff08;或电脑屏幕上&#xff09;&#xff0c;所以人们想出了各种巧妙的解决方案&#xff08;投影&#xff09;。 每种投影方案都有优点和缺点&#xff0c;一…

LabVIEW使用单板RIO开发远程监控电源信号

LabVIEW使用单板RIO开发远程监控电源信号 设计和构建用于智能电网的本地功耗分析系统&#xff0c;主要服务于领先的电力监控设备设计者和制造商。随着智能电网投资的增加&#xff0c;对于能够有效处理替代电源&#xff08;如太阳能和风能&#xff09;间歇性功率水平的技术需求…

揭秘强化学习:Python 实践指南

一、说明 强化学习 (RL) 是机器学习和人工智能 (AI) 的一个子领域&#xff0c;专注于开发能够通过与环境交互进行学习的智能代理。与传统的监督和无监督学习不同&#xff0c;强化学习主要关注动态、顺序环境中的决策。它在人工智能中具有重要意义&#xff0c;特别是在自主代理必…

数字与数学基础问题

关卡名 数字与数学基础问题 我会了✔️ 内容 1.数字里统计的处理技巧 ✔️ 2.必须熟练掌握溢的处理方法 ✔️ 3.掌握进制的处理方法 ✔️ 1. 数字统计专题 统计一下特定场景下的符号&#xff0c;或者数字个数等是一类非常常见的问题 。如果按照正常方式强行统计&#xf…

MX6ULL学习笔记 (八) platform 设备驱动实验

前言&#xff1a; 什么是 Linux 下的 platform 设备驱动 Linux下的字符设备驱动一般都比较简单&#xff0c;只是对IO进行简单的读写操作。但是I2C、SPI、LCD、USB等外设的驱动就比较复杂了&#xff0c;需要考虑到驱动的可重用性&#xff0c;以避免内核中存在大量重复代码&…

uc_13_共享内存_消息队列_IPC对象

1 IPC对象 多个IPC -> 一个IPC对象 -> 一个IPC对象标识符 -> 一个键(整数)(即IPC对象的外部名称) 共享内存、消息队列和信号量&#xff0c;这三种IPC一般被合称为XSI IPC&#xff0c;它们有很多相似之处。 为了实现进程间的数据交换&#xff0c;系统内核会为参…

dockerfile简单实践部署(jenkins,wordpress)

实现部署jenkins的流程 配置java环境&#xff0c;导入jenkins包&#xff0c;运行命令 java -jar jenkins包&#xff0c;这里为了减少进入jenkins的web端安装插件&#xff0c;将插件提前部署到容器内。 制作dockerfile 创建镜像所在的文件夹和Dockerfile文件 mkdir /test cd …

【项目日记(一)】高并发内存池项目介绍

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:项目日记-高并发内存池⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; 项目日记 1. 前言2. 什么是高并发内存池…

Textual Inversion

参考博客1:https://www.bilibili.com/read/cv25430752/

移动云荣获OpenInfra社区“算力基础设施技术突破奖”

近日&#xff0c;一年一度的 OpenInfra Days China在北京召开&#xff0c;大会汇聚了全球各大云厂商的技术专家&#xff0c;共同分享全球前沿基础设施技术的展望和实践经验。在本次大会上&#xff0c;移动云荣获OpenInfra社区颁发的“算力基础设施技术突破奖”&#xff0c;表明…