算法刷题Day4 | 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II

目录

  • 0 引言
  • 1 两两交换链表中的节点
    • 1.1 我的解题
    • 1.2 注意事项
  • 2 删除链表的倒数第N个节点
    • 2.1 我的代码
    • 2.2 报错原因分析
  • 3 链表相交
    • 3.1 我的解题
  • 4 环形链表II
    • 4.1 我的解题

请添加图片描述

  • 🙋‍♂️ 作者:海码007
  • 📜 专栏:算法专栏
  • 💥 标题:算法刷题Day4 | 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II
  • ❣️ 寄语:书到用时方恨少,事非经过不知难!

0 引言

1 两两交换链表中的节点

  • 🎈 文档讲解:https://programmercarl.com/0024.%E4%B8%A4%E4%B8%A4%E4%BA%A4%E6%8D%A2%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B9.html
  • 🎈 视频讲解:
  • 🎈 做题状态:没看题解就写出来了,比较顺利

1.1 我的解题

这一次还是会涉及到头结点和非头结点处理的差别,所以引入了虚拟头结点统一操作。
这一题涉及到三个指针,cur、pre、tmp。一定要注意cur是从虚拟头结点开始遍历。然后当 cur->next; cur->next->next; cur的后面两个节点都存在时才能进行遍历。可以先看图解的思路

在这里插入图片描述

class Solution {
public:ListNode* swapPairs(ListNode* head) {// 创建虚拟头结点ListNode* dummyNode = new ListNode(-1);dummyNode->next = head;// 创建三个节点指针,主要为了完成交换操作ListNode* cur = dummyNode;ListNode* pre;ListNode* tmp;// 当cur指针、cur的下一个节点指针、以及下下一个指针存在时,才能进行交换// 因为cur第一次指向的是虚拟头结点,后面两个指针才是真正的数据while ( cur && cur->next && cur->next->next){pre = cur->next;tmp = pre->next;    // tmp可以为空指针,不影响// 交换节点cur->next = tmp;pre->next = tmp->next;tmp->next = pre;// 交换完成后,cur指针向后移动两位,因为是两两交换cur = cur->next->next;}return dummyNode->next;}
};

1.2 注意事项

一定要画图,不画图,操作多个指针很容易乱,而且要操作的先后顺序。

2 删除链表的倒数第N个节点

  • 🎈 文档讲解:
  • 🎈 视频讲解:
  • 🎈 做题状态:通过画图,然后写下步骤,做题变轻松很多

2.1 我的代码

具体思路如下
在这里插入图片描述

class Solution {
public:ListNode* removeNthFromEnd(ListNode* head, int n) {// 1. 创建虚拟头结点ListNode* dummyNode = new ListNode(0);dummyNode->next = head;// 2. 循环n次,将right指针移动到正确位置ListNode* left = dummyNode;ListNode* right = dummyNode;for (int i = 0; i < n; i++){right = right->next;// 如果倒数第n个节点不存在,则直接返回if (right == nullptr) return dummyNode->next;}// 3. 遍历到最后的空节点while (right->next != nullptr){right = right->next;left = left->next;}std::cout << "right->val = " << right->val;// 4. 删除节点ListNode* tmp = left->next;left->next = tmp->next;delete tmp;return dummyNode->next;}
};

2.2 报错原因分析

但是我在删除目标节点的时候报错了,因为我应该将 left->next = tmp->next; 而不是指向right 节点。

在这里插入图片描述

3 链表相交

  • 🎈 文档讲解:https://programmercarl.com/%E9%9D%A2%E8%AF%95%E9%A2%9802.07.%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4.html
  • 🎈 视频讲解:https://programmercarl.com/%E9%9D%A2%E8%AF%95%E9%A2%9802.07.%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4.html
  • 🎈 做题状态:没太大问题

3.1 我的解题

需要注意的就是,判断的是节点的地址是否相等,而不是节点内存储的val是否相等

在这里插入图片描述

class Solution {
public:ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {// 创建虚拟头结点(和前面思路保持一致,习惯使用虚拟头结点)ListNode* dummyA = new ListNode(0);dummyA->next = headA;ListNode* dummyB = new ListNode(0);dummyB->next = headB;// 1.确定最小的长度值int sizeA = 0;int sizeB = 0;ListNode* curA = dummyA->next;while (curA != nullptr){sizeA++;curA = curA->next;}ListNode* curB = dummyB->next;while (curB != nullptr){sizeB++;curB = curB->next;}// 2. 将curA 和 curB 指针对齐// 注意此时需要重新给 curA 和 curB 重置到起始位置curA = dummyA->next;curB = dummyB->next;if (sizeA > sizeB){// 当链表A较长时,需要移动 curA 指针和 curB对齐int dValue = sizeA - sizeB;while (dValue > 0){curA = curA->next;dValue--;}}else if (sizeA < sizeB){// 当链表B较长时,需要移动 curB 指针和 curA 对齐int dValue = sizeB - sizeA;while (dValue > 0){curB = curB->next;dValue--;}}// 3. 开始遍历 curA 和 curB ,看什么时候元素值相等while (curA != nullptr && curA != curB){curA = curA->next;curB = curB->next;}return curA;}
};

4 环形链表II

  • 🎈 文档讲解:https://programmercarl.com/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.html
  • 🎈 视频讲解:https://programmercarl.com/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.html
  • 🎈 做题状态:有难度

4.1 我的解题

不看题解写不出来,虽然已经想到了快慢指针确定是否有环,但是不知道该如何确定环的入口位置。

有两个关键点:

  • 快慢指针为什么一定会在环内相遇

    • 因为判断是否相遇时,不仅移动完快指针后会判断,移动慢指针后也会判断。所以就算快指针跳过慢指针,慢指针移动上去后还是会相遇。
    • 下图是代码随想录中的图片,图中的快指针就是刚好跳过慢指针,但是慢指针移动后就相遇了。在这里插入图片描述
  • 如何确定环的入口。

    • 根据快慢指针的关系,可以推到出 x = (n - 1) (y + z) + z 公式。
    • 然后在快慢指针相遇的时候,再新建一个指针 cur 从头结点位置出发,然后 cur 指针一定会和慢指针在环的入口处相遇。
      在这里插入图片描述

解题步骤(本题没有头结点特殊情况)

  1. 定义快慢指针,并初始化到头结点位置。
  2. 移动快指针移动两次,移动慢指针一次,然后判断是否相等,如果相等则找到相遇点。
  3. 找到相遇点后,再新建一个指针 cur ,然后循环遍历知道 cur 指针和 slow 指针相遇,相遇的节点就是环的入口节点。
class Solution {
public:ListNode *detectCycle(ListNode *head) {ListNode* fast = head;ListNode* slow = head;ListNode* cur = head;// 循环条件是 fast 不为空指针while ( fast!= nullptr ){fast = fast->next;// 由于 fast 要移动两次,所以每移动一次都需要判断是否为空if ( fast != nullptr ){fast = fast->next;slow = slow->next;if (fast == slow) break;}else{return nullptr;}}// 如果 fast 为空说明链表没有环,则返回空if (fast == nullptr) return nullptr;cout << "环的入口节点的值 = " << slow->val;// 新建一个指针从head开始遍历while (cur != slow){cur = cur->next;slow = slow->next;}// cur 和 slow 相遇后退出循环,此时cur的位置就是环的入口节点return cur;}
};

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

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

相关文章

真空泵系统数据采集远程监控解决方案

行业背景 半导体制造业可以说是现代电子工业的核心产业&#xff0c;广泛应用于计算机、通信、汽车、医疗等领域。而在半导体生产加工过程中&#xff0c;如刻蚀、 镀膜、 扩散、沉积、退火等环节&#xff0c;真空泵都是必不可少的关键设备&#xff0c;它可以构建稳定受控的真空…

灵雀云开源ALB ,为云原生 Kubernetes 网关领域再添新星

ALB (Another Load Balancer)是一款由灵雀云倾力打造的云原生 Kubernetes 网关&#xff0c;近日&#xff0c;正式宣布将其在Github上开源。ALB 的诞生&#xff0c;旨在满足日益增长的云原生应用需求&#xff0c;为开发者提供更为强大和灵活的网关解决方案。 ALB 支持在一个集群…

淘宝基于Nginx二次开发的Tengine服务器

最近在群里看到这样一张阿里云网关报错的截图&#xff0c;我保存下来看了下 看到下面有 Tengine提供技术支持&#xff0c;这个Tengine是什么东西呢&#xff1f;我搜索了下似乎是淘宝在nginx的基础上自己改的Web服务器 Tengine还支持OpenResty框架&#xff0c;该框架是基于Ngin…

设计模式系列之-策略模式(优化过多代码if…else)

首先解释下什么策略模式 如下图&#xff1a; 简而言之&#xff1a;算法的使用与算法的实现分离开来 想象有一个开关按钮&#xff0c;每次按下去都可以切换不同的灯光模式&#xff08;例如&#xff1a;强光、柔光、闪烁&#xff09;&#xff0c;这里的每种灯光模式就是一个策略…

零基础自学C语言|自定义类型:联合与枚举

✈联合体 &#x1f680;联合体的类型声明 像结构体一样&#xff0c;联合体也是由一个或者多个成员构成&#xff0c;这些成员可以不同的类型。 但是编译器只为最大的成员分配足够的内存空间。联合体的特点是所有成员共用同一块内存空间。所以联合体也叫&#xff1a;共用体。 给…

如何进行软件安全性测试?CMA、CNAS软件安全测试报告获取

软件安全性测试是保障软件应用安全的重要手段&#xff0c;通过对软件系统的安全性进行全面评估和检测&#xff0c;以确保软件能够抵御各种潜在的安全威胁和风险。那么如何进行软件安全性测试?CMA、CNAS软件安全测试报告又该如何获取呢? 软件安全性测试是一种基于黑盒测试的方…

Rabbit算法:轻量高效的加密利器

title: Rabbit算法&#xff1a;轻量高效的加密利器 date: 2024/3/13 18:14:31 updated: 2024/3/13 18:14:31 tags: Rabbit算法流密码高安全性高性能密钥调度加密解密抗攻击性 Rabbit算法起源&#xff1a; Rabbit算法是由Martin Boesgaard和Mette Vesterager提出的一种流密码算…

以客户为中心、以市场为导向的创新研发能力:塑造企业核心竞争力的关键

在当今竞争激烈的市场环境中&#xff0c;企业的生存与发展往往取决于其核心竞争力。其中&#xff0c;以客户为中心、以市场为导向的创新研发能力&#xff0c;成为了塑造企业核心竞争力的关键要素。本文将探讨这一观点&#xff0c;并结合实际案例进行分析。 一、以客户为中心&am…

React进阶(Redux,RTK,dispatch,devtools)

1、初识Redux 是React最常用的集中状态管理工具&#xff0c;类似于Vue中的Pinia(Vuex)&#xff0c;可以独立于框架运行 作用&#xff1a;通过集中管理的方式管理应用的状态 案例-实现一个计数器 实现步骤&#xff1a; Redux管理数据的流程&#xff1a; state:一个对象&…

docker私有仓库-harbor的搭建

docker 官方提供的私有仓库 registry&#xff0c;用起来虽然简单 &#xff0c;但在管理的功能上存在不足。 Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器&#xff0c;harbor使用的是官方的docker registry(v2命名是distribution)服务去完成。harbor在docker di…

解决Ubuntu 16.04/18.04 图形化界面异常、鼠标光标消失、鼠标变成叉叉等问题

bug场景&#xff1a; 一切从一次换源说起…叭叭叭 这篇文章解决的问题&#xff1a; 1.换源&#xff0c;默认源太慢&#xff0c;换成可用的阿里云的源 2.apt-get failed to …问题 3.图形化异常问题 4.get unmet dependence 问题 5. 鼠标光标消失和鼠标变成叉叉问题。 解决方…

DevOps方案中10款最佳开源监控工具

DevOps方案中10款最佳开源监控工具 2024年,监视对现代DevOps团队的工作至关重要。DevOps团队需要可靠且灵活的工具,以有效监视和管理复杂系统,这些系统可以提供有关系统性能、可用性和安全性的实时见解。 开源监控工具由于其成本效益、灵活性和社区支持而日益受到青睐。 …