1. 题目
描述
给定一个链表,请判断该链表是否为回文结构。
回文是指该字符串正序逆序完全一致。
数据范围: 链表节点数 0≤n≤105,链表中每个节点的值满足 ∣val∣≤107
示例1
输入:
{1}
返回值:
true
示例2
输入:
{2,1}
返回值:
false
说明:
2->1
示例3
输入:
{1,2,2,1}
返回值:
true
说明:
1->2->2->1
2. 解题思路
判断一个链表是否为回文结构,可以先将链表从中间分为两部分,对后半部分进行反转。之后依次对比前半部分链表与后半部分反转之后的节点值。难点在于如何找到中间节点(链表节点数量可能为偶数,也可能为奇数)。链表的反转参考前期的文章《可视化图解算法:反转链表》。
假如有两个链表,结构如下图所示:
步骤一:通过快慢指针分割链表(链表分割为:左右两部分)。
快慢指针变量的定义如下:
注意:fast初始化时指向的节点为slow的下一个节点。
当节点数量为偶数时,fast.next==Null,停止查找。slow.next为后半部分链表的起始点。
当节点数量为奇数时,fast==Null,停止查找。slow节点为中间节点,slow.next为后半部分链表的起始点(前半部分多一个节点)。
步骤二:反转后半部分链表。
步骤三:前后两部分链表节点值对比(判断节点值是否相等)。
如果文字描述的不太清楚,你可以参考视频的详细讲解。
- Python版本:https://www.bilibili.com/cheese/play/ep1370399
- Java版本:https://www.bilibili.com/cheese/play/ep1366843
- Golang版本:https://www.bilibili.com/cheese/play/ep1364600
3. 编码实现
核心伪代码如下:
函数 判断回文链表(head: 链表节点) -> 布尔值:// 步骤1: 使用快慢指针分割链表fast = head.nextslow = head当 fast 不为空 且 fast.next 不为空:fast = fast.next.next // 快指针每次移动两步slow = slow.next // 慢指针每次移动一步new_node = slow.next // 后半部分链表的起点slow.next = 空 // 断开链表,分割为左右两部分left = head // 左半部分头节点// 步骤2: 反转右半部分链表right = 反转链表(new_node) // 调用反转链表函数// 步骤3: 比较左右两部分的节点值当 right 不为空:如果 right.val != left.val:返回 Falseright = right.next // 右半部分指针后移left = left.next // 左半部分指针后移返回 True // 所有节点值匹配,是回文
具体完整代码你可以参考下面视频的详细讲解。
- Python版本:https://www.bilibili.com/cheese/play/ep1370399
- Java版本:https://www.bilibili.com/cheese/play/ep1366843
- Golang版本:https://www.bilibili.com/cheese/play/ep1364600
4.小结
判断一个链表是否为回文结构,可以先将链表从中间分为两部分,对后半部分进行反转。之后依次对比前半部分链表与后半部分反转之后的节点值。难点在于找到中间节点(可以通过快慢指针查找到中间节点)。
更多数据结构与算法视频讲解,你可以从以下地址找到:
- Python编码实现:https://www.bilibili.com/cheese/play/ep1509965
- Java编码实现:https://www.bilibili.com/cheese/play/ep1510007
- Golang编码实现:https://www.bilibili.com/cheese/play/ep1509945
对于链表的相关操作,我们总结了一套【可视化+图解】方法,依据此方法来解决链表相关问题,链表操作变得易于理解,写出来的代码可读性高也不容易出错。具体也可以参考视频详细讲解。
今日佳句:路虽远行则将至,事虽难做则必成。