登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
广播
Follow
园子
关于
博客
发1篇日志+1圆
记录
发1条记录+2圆币
发帖说明
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
CSDN热搜
程序园
精品问答
技术交流
资源下载
本版
帖子
用户
软件
问答
教程
代码
VIP申请
网盘
联系我们
道具
勋章
任务
设置
我的收藏
退出
腾讯QQ
微信登录
返回列表
首页
›
业界区
›
科技
›
【忍者算法】从生活场景到回文链表:探索对称性检测|Le ...
【忍者算法】从生活场景到回文链表:探索对称性检测|LeetCode 234 回文链表
[ 复制链接 ]
辈霖利
12 小时前
从生活场景到回文链表:探索对称性检测
生活中的回文现象
在日常生活中,回文无处不在。比如"上海自来水来自海上"、"12321"这样正着读和倒着读都一样的字符串或数字,就是回文。把这个概念扩展到链表,我们就得到了今天要讨论的回文链表问题:一个链表从前往后读和从后往前读的结果是否相同。
问题描述
LeetCode第234题"回文链表"要求:给你一个单链表的头节点 head,请判断该链表是否为回文链表。
例如:
输入:1 → 2 → 2 → 1
输出:true
输入:1 → 2 → 3 → 2 → 1
输出:true
输入:1 → 2 → 3 → 3 → 1
输出:false
复制代码
基础知识准备
这道题的核心是利用我们之前学过的"反转链表"。如果不熟悉链表反转,建议先复习上一篇文章。记住,链表反转是一块基石,在这里我们要用它来解决更复杂的问题。
直观解法:转换为数组
最简单的想法是:把链表转换成数组,然后用双指针从两端向中间移动比较。这就像把一摞扑克牌摊开在桌上,从两端开始对比每张牌是否相同。
数组法实现
public boolean isPalindrome(ListNode head) {
List<Integer> vals = new ArrayList<>();
// 将链表值复制到数组中
ListNode current = head;
while (current != null) {
vals.add(current.val);
current = current.next;
}
// 使用双指针判断是否回文
int left = 0, right = vals.size() - 1;
while (left < right) {
if (!vals.get(left).equals(vals.get(right))) {
return false;
}
left++;
right--;
}
return true;
}
复制代码
优化解法:反转后半部分
仔细思考,我们其实不需要额外的数组。可以用这个巧妙的方法:
找到链表中点
反转后半部分
比较前后两半是否相同
(可选)恢复链表原状
这就像把一叠纸牌分成两半,把后半部分倒过来,然后一张张对比。
寻找中点:快慢指针法
想象两个人在跑道上跑步,一个速度是另一个的两倍。当快跑者跑到终点时,慢跑者正好在中点!
详细代码实现
public boolean isPalindrome(ListNode head) {
if (head == null || head.next == null) {
return true;
}
// 第1步:找到中点
ListNode slow = head;
ListNode fast = head;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// 第2步:反转后半部分
ListNode secondHalf = reverseList(slow.next);
// 第3步:比较两半是否相同
ListNode firstHalf = head;
ListNode temp = secondHalf; // 保存开始位置,用于之后恢复
boolean result = true;
while (secondHalf != null) {
if (firstHalf.val != secondHalf.val) {
result = false;
break;
}
firstHalf = firstHalf.next;
secondHalf = secondHalf.next;
}
// 第4步:恢复链表(可选)
slow.next = reverseList(temp);
return result;
}
// 链表反转函数(使用我们之前学过的方法)
private ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
复制代码
图解过程
以1→2→3→2→1为例:
1) 初始状态:
1 → 2 → 3 → 2 → 1
2) 找到中点:
1 → 2 → [3] → 2 → 1
slow指向3
3) 反转后半部分:
1 → 2 → 3 ← 2 ← 1
4) 比较两半:
(1 → 2) 和 (1 → 2) 比较
5) 恢复原状:
1 → 2 → 3 → 2 → 1
复制代码
复杂度分析
空间优化解法:
时间复杂度:O(n)
空间复杂度:O(1),只使用几个指针
优点:空间效率高,且思路优雅
缺点:修改了原链表结构(虽然最后恢复了)
重要思维方式总结
问题转化
:将回文判断转化为对称性比较
空间优化思维
:
不用额外数组存储
利用原有空间进行操作
分步思想
:
找中点(快慢指针)
反转后半段(链表反转)
对比(双指针)
恢复(再次反转)
边界处理
:
空链表
单节点链表
偶数/奇数长度的处理
实用技巧总结
解决类似问题的关键点:
熟练掌握基础操作(如链表反转)
善用快慢指针找中点
考虑空间优化的可能性
注意保护原始数据结构
相关的思维训练:
回文数判断
回文子串问题
链表中点问题
链表反转的各种变体
小结
回文链表问题是一个很好的例子,展示了如何将基础算法(如链表反转、快慢指针)组合起来解决更复杂的问题。它教会我们:
基础算法的重要性
空间优化的思维方式
问题分解的方法
代码的优雅性
下次遇到类似的对称性判断问题,不要急着用额外空间,想想是否可以通过改变数据结构本身来解决问题!
作者:忍者算法
公众号:忍者算法
我准备了一份刷题清单,以及这些题目的详细题解,覆盖了绝大部分常见面试题。我可以很负责任地说,只要你把这些题真正掌握了,80%的算法面试都能遇到相似题目。公众号回复【刷题清单】获取~
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
相关推荐
我的笔记
数据结构-基本概念
可视化图解算法06:合并两个有序(排序)的链表
k8s单机容器网络(20250216)
《Fundamentals Of Computer Graphics》第二章 杂项数学 总结
Golang+Gin实现api接口搭建
CTFHub技能树-信息泄露wp
游戏编程模式(28种编程模式)
刷题笔记Day29贪心算法part03
路径选择,调试运行,自定义图表ECharts,分页渲染
Kioptrix-Level Two
关于专项附加扣除和个税年度汇算的相关知识
算法day02-数组篇(2)
Codeforces Round 1020 (Div. 3)
用Logseq记日报和管理文献
缺陷分析方法简介
性能王者!天翼云再次拿下世界第一
刷题笔记Day28贪心算法part02
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
签约作者
程序园优秀签约作者
发帖
辈霖利
12 小时前
关注
0
粉丝关注
11
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
敖可
9988
森萌黠
9996
堵赫然
9996
4
凶契帽
9996
5
处匈跑
9996
6
柴古香
9996
7
背竽
9996
8
斜素欣
9994
9
恐肩
9994
10
里豳朝
9994
查看更多