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

【LeetCode】链表经典问题解析:环形、回文与相交

文章目录

  • 一、判断环形链表
    • 问题描述
    • 解题思路
    • 代码实现
  • 二、环形链表 II
    • 问题描述
    • 解题思路
    • 代码实现
  • 三、判断链表的回文结构
    • 问题描述
    • 解题思路
    • 代码实现
  • 四、相交链表
    • 问题描述
    • 解题思路
    • 代码实现

一、判断环形链表

问题描述

给定一个链表的头节点 head,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。
在这里插入图片描述

解题思路

  • 初始化快指针 fast 和慢指针 slow 都指向头节点 head
  • 在循环中,快指针每次移动两步,慢指针每次移动一步。
  • 若快慢指针相遇,说明链表存在环,返回 true;若快指针走到末尾(fastfast.nextnull),说明链表无环,返回 false

代码实现

public class Solution {public boolean hasCycle(ListNode head) {ListNode fast = head;ListNode slow = head;while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;if (slow == fast) {return true;}}return false;}
}

二、环形链表 II

问题描述

给定一个链表的头节点 head,返回链表开始入环的第一个节点。如果链表无环,则返回 null。

解题思路

  1. 首先用快慢指针法判断链表是否有环,若快慢指针相遇,说明有环。
  2. 若有环,假设起点到环起点距离为X,环的距离为C,相遇点到环起点距离为Y
  3. 因为快指针速度为慢指针2倍,所以到相遇,快指针路程也是慢指针的2倍,经过计算得到X == Y。
  4. 将慢指针重新指向头节点,然后快慢指针每次都移动一步,当它们再次相遇时,相遇节点就是入环的第一个节点。
    在这里插入图片描述

代码实现

public class Solution {public ListNode detectCycle(ListNode head) {ListNode fast = head;ListNode slow = head;// 判断是否有环while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;if (slow == fast) {break;}}// 无环情况if (fast == null || fast.next == null) {return null;}// 找入环第一个节点slow = head;while (slow != fast) {fast = fast.next;slow = slow.next;}return slow;}
}

三、判断链表的回文结构

问题描述

对于一个链表,设计时间复杂度为 (O(n))、额外空间复杂度为 (O(1)) 的算法,判断其是否为回文结构。

解题思路

  1. 用快慢指针找到链表的中间节点。

  2. 反转中间节点之后的链表部分。
    在这里插入图片描述

  3. 从原来链表的头和尾依次比较节点值是否相等,若都相等则为回文链表。

代码实现

public class Solution {public boolean chkPalindrome(ListNode A) {if (A == null || A.next == null) {return true;}ListNode slow = A;ListNode fast = A;// 找中间节点while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;}// 反转后半部分链表ListNode cur = slow.next;ListNode curNext;while (cur != null) {curNext = cur.next;cur.next = slow;slow = cur;cur = curNext;}// 比较原链表前半部分和反转后的后半部分ListNode first = A;while (first != slow) {if (first.val != slow.val) {return false;}// 处理偶数长度链表的终止情况if (first.next == slow) {return true;}first = first.next;slow = slow.next;}return true;}
}

注意:
反转后半个列表后slow就在原列表尾部,所以由first从前往后,slow从后往前遍历列表

  • 奇数个节点:当slow.val == first.val即为遍历完成
  • 偶数个节点:不可以直接按照奇数个的情况来判断,因为会出现firstslow互换的情况。当 first.next==slow即遍历完成
    在这里插入图片描述

四、相交链表

问题描述

给你两个单链表的头节点 headAheadB,找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null
在这里插入图片描述

解题思路

  1. 分别计算两个链表的长度 lenAlenB
  2. 让较长的链表先移动长度差的步数,使得两个链表剩余部分长度相同。
  3. 然后同时移动两个链表的指针,若指针相遇,则相遇节点为相交起始节点;若遍历结束都未相遇,则无相交节点。

代码实现

public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {if (headA == null || headB == null) {return null;}ListNode pl = headA;ListNode ps = headB;int lenA = 0;int lenB = 0;while (pl != null) {lenA++;pl = pl.next;}while (ps != null) {lenB++;ps = ps.next;}int len = lenA - lenB;pl = headA;ps = headB;if (len < 0) {len = -len;pl = headB;ps = headA;}for (int i = 0; i < len; i++) {pl = pl.next;}while (ps != pl) {ps = ps.next;pl = pl.next;}return pl;}
}
http://www.dtcms.com/a/391191.html

相关文章:

  • 电磁超材料及其领域应用优势
  • STM32与Modbus RTU协议实战开发指南-fc3ab6a453
  • ArrayList 与 LinkedList 深度对比:从原理到场景的全方位解析
  • Ubuntu和windows复制粘贴互通
  • 银行回单 OCR 识别:财务自动化的 “数据入口“
  • 深兰科技陈海波的AI破局之道:打造软硬一体综合竞争力|《中国经营报》专访
  • 面试经验之mysql高级问答深度解析
  • 高质量票据识别数据集:1000张收据图像+2141个商品标注,支持OCR模型训练与文档理解研究
  • 嵌入式音视频开发——FFmpeg入门
  • MySQL索引篇---B+树在索引中的工作原理
  • 强化学习训练-数据处理
  • VirtualBox为ubuntu系统设置共享文件夹
  • Python实战进阶》No.41: 使用 Streamlit 快速构建 ML 应用
  • Salesforce 执行顺序(Order of Execution)详解
  • Linux内核进程管理子系统有什么第五十七回 —— 进程主结构详解(53)
  • Vue 记账凭证模块组件
  • ORACLE-数据库闪回
  • 【Python】集合
  • 【Leetcode hot 100】437.路径总和 Ⅲ
  • 神经网络学习笔记16——高效卷积神经网络架构汇总(SqueezeNet、MobileNet、ShuffleNet、EfficientNet、GhostNet)
  • 解码阳光电源技术壁垒:以IPD和数字化驱动模块化创新的研发体系
  • ARM体系结构—架构—指令集—寄存器—工作模式
  • 自适应全变分模型的图像平滑去噪与边缘保留算法
  • 主流前端框架比较
  • 前端接口参数序列化
  • 精细调光,稳定驱动:AP5165B 在低压LED照明中的卓越表现
  • EasyGBS如何实现企业园区视频监控一体化管理?
  • Ledit 16.3 版图软件全面系统性教程
  • Linux的DTS配置信息
  • 线程池全面解析:核心原理、参数配置与实践指南