当前位置: 首页 > news >正文

[豪の算法奇妙冒险] 代码随想录算法训练营第四天 | 24-两两交换链表中的节点、19-删除链表的倒数第N个节点、面试题02.07-链表相交、142-环形链表II

代码随想录算法训练营第四天 | 24-两两交换链表中的节点、19-删除链表的倒数第N个节点、面试题02.07-链表相交、142-环形链表II


LeetCode24-两两交换链表中的节点

题目链接:https://leetcode.cn/problems/swap-nodes-in-pairs/description/

文章讲解:https://programmercarl.com/0024.两两交换链表中的节点.html

视频讲解:https://www.bilibili.com/video/BV1YT411g7br/?vd_source=b989f2b109eb3b17e8178154a7de7a51

​ 一拿到题目,我的思路是采用虚拟头节点保存Head的初始位置,先单独排除无元素和一个元素的情况,接着再单独处理两个元素的情况,之后如果符合条件再进行循环交换

​ 循环交换的时候,使用pre、cur和after三个指针遍历链表,进行cur和after所指节点的两两交换,关键在于确定何时停止循环和避免操作空指针

​ 总的来说还是要多画图、多分析

image-20251124092127596

class Solution {public ListNode swapPairs(ListNode head) {ListNode dummyHead = head;if(dummyHead == null || dummyHead.next == null){return dummyHead;}ListNode pre = null;ListNode cur = dummyHead;ListNode after = dummyHead.next;cur.next = after.next;after.next = cur;dummyHead = after;pre = cur;cur = cur.next;while(cur != null){after = cur.next;if(after == null){break;}pre.next = after;cur.next = after.next;after.next = cur;pre = cur;cur = cur.next;}return dummyHead;}
}

​ 看完Carl哥的讲解后,发现我的这个解法还能再活用dummyHead,进行逻辑的优化,统一操作链表,代码也更加简洁明了

image-20251124210232359

class Solution {public ListNode swapPairs(ListNode head) {ListNode dummyHead = new ListNode();dummyHead.next = head;ListNode cur = dummyHead;while(cur.next != null && cur.next.next != null){ListNode pre = cur.next;ListNode after = cur.next.next.next;cur.next = cur.next.next;cur.next.next = pre;pre.next = after;cur = cur.next.next;}return dummyHead.next;}
}

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

题目链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/

文章讲解:https://programmercarl.com/0019.删除链表的倒数第N个节点.html

视频讲解:https://www.bilibili.com/video/BV1vW4y1U7Gf/?vd_source=b989f2b109eb3b17e8178154a7de7a51

​ 采用快慢指针的思想解,快指针从dummyHead出发,先往后移动 n+1 步,然后快慢指针一起往后移动,直到快指针指向null,此时慢指针指向的是要删除的节点的前一个节点

image-20251124211822387

class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dummyHead = new ListNode();dummyHead.next = head;ListNode fast = dummyHead;ListNode slow = dummyHead;for(int i = 1;i <= n+1;i++){fast = fast.next;}while(fast != null){fast = fast.next;slow = slow.next;}slow.next = slow.next.next;return dummyHead.next;}
}

面试题02.07 链表相交

题目链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/description/

文章讲解:https://programmercarl.com/面试题02.07.链表相交.html

​ 拿到题第一眼想到的是双重for循环暴力解,注意单个节点的情况,劈里啪啦写完发现居然能过,但这份代码一点也不优雅,而且时间复杂度来到O(n^2),得改!

image-20251124215047231

public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {if(headA == headB){return headA;}for(ListNode pA = headA; pA != null; pA = pA.next){for(ListNode pB = headB; pB != null; pB = pB.next){if(pA == pB){return pA;}}}return null;}
}

​ 看了题解后自己又写了一遍,大开眼界:可以先求出AB两个链表的长度,然后求出两个链表长度差值,让两个链表的末尾对齐,curA和curB对齐相对短的那一个,然后比较curA和curB是否相同,不同则同时往后移动curA和curB,如果遇到相同的情况则找到了交点,否则返回null。妙呀妙呀!

image-20251124220719855

public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {ListNode curA = headA;ListNode curB = headB;int lengthA = 1;int lengthB = 1;while(curA != null){curA = curA.next;lengthA++;}while(curB != null){curB = curB.next;lengthB++;}curA = headA;curB = headB;if(lengthA >= lengthB){for(int i = 1;i <= lengthA - lengthB;i++){curA = curA.next;}}else{for(int i = 1;i <= lengthB - lengthA;i++){curB = curB.next;}}while(curA != null){if(curA == curB){return curA;}curA = curA.next;curB = curB.next;}return null;}
}

LeetCode142 环形链表II

题目链接:https://leetcode.cn/problems/linked-list-cycle-ii/description/

文章讲解:https://programmercarl.com/0142.环形链表II.html

视频讲解:https://www.bilibili.com/video/BV1if4y1d7ob/?vd_source=b989f2b109eb3b17e8178154a7de7a51

​ 这题解法相当的妙呀,先定义一个快指针和一个慢指针,快指针每次往后走两个节点,慢指针每次往后走一个节点,它们如果相遇则说明链表存在环

​ 接着,由数学推理可以得出,从head到环入口的距离 = (n-1)圈环的距离 + 快慢指针相遇点到环入口的距离

​ 由此可以再定义index1从快慢指针相遇点出发,index2从head出发,它们都每次往后走一个节点,这样index1和index2相遇的节点即为环的入口节点

image-20251124223024764

public class Solution {public ListNode detectCycle(ListNode head) {ListNode fast = head;ListNode slow = head;while(fast != null && fast.next != null && fast.next.next != null){fast = fast.next.next;slow = slow.next;if(fast == slow){ListNode index1 = fast;ListNode index2 = head;while(index1 != index2){index1 = index1.next;index2 = index2.next;}return index1;}}return null;}
}
http://www.jsqmd.com/news/49780/

相关文章:

  • 【Android】详细讲解ViewDragHelper的达成原理(不含代码版)
  • 不那么详细的多项式笔记
  • Java的线程池了解吗?
  • 超简单!3步生成10W+爆款说唱视频!
  • 深度解析2026美国研究生申请机构:从GPA到藤校,这些机构藏着关键方案
  • 实用指南:介绍一下Ribbon
  • P27_完整的模型训练套路(二)
  • 洛谷 P1496:火烧赤壁 ← 离散化(数组 + sort + STL map)
  • P28_完整的模型训练套路(三)
  • 奶酪和机器人 非标准化的步数遍历
  • 6个适合做 PoC 的开源无代码/低代码工具推荐
  • 2025年度木门厂商推荐榜单与选择指南:一份基于行业专业数据的权威分析报告,整木/实木/原木门十大主流供应商解析
  • C# Quartz 定损执行 - microsoft
  • 2025美国本科申请中介深度解析:适配不同背景的梦校推手,谁能助你敲开美国名校门?
  • Rokid AI眼镜开发 —— 戴上Rokid Glasses的你有多强
  • 机器人的记忆化搜索
  • # 数据库对AI向量语义搜索的支持深度分析:PostgreSQL、MySQL、Elasticsearch技术选型指南
  • # 编程十四年感悟:复杂度管理与工程实践
  • Ai元人文:行为化不是放弃概念,而是通往概念的坚实阶梯
  • 基于RS485通讯及Modbus通讯协议的温湿度变送器
  • 小额支付系统:详细处理逻辑(底层)
  • “大概率上涨”的推荐
  • Day1 Scrum冲刺博客
  • 六、设备树与设备树插件
  • 【设计模式笔记06】:单一职责原则 - 实践
  • 102302124_严涛_作业3
  • CF1799G Count Voting 笔记
  • 2025年11月美国本科申请机构深度测评:藤校Offer领航者全解析
  • 20251124 - 月度检测 总结
  • 2026美国硕士留学中介推荐:从背景提升到签证获批全程护航!