LeetCode234 回文链表
题目
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
方法
栈方法
先计算链表长度,若为偶数,将前半个链表数值存入栈,后半个链表验证与栈中数据是否一致
- 时间复杂度:O(n)
- 空间复杂度:O(n)
Java版本
class Solution {
public boolean isPalindrome(ListNode head) {
if(head==null||head.next==null){
return true;
}
int len = 0; //获取链表长度
ListNode node = head;
while(node!=null){
len++;
node = node.next;
}
Stack<Integer> stack = new Stack<>();
node = head;//把前半个链表存入栈
for(int i=0;i<len/2;i++){
stack.add(node.val);
node = node.next;
}
if(len%2!=0){
node = node.next; //若为奇数个,跳过中间的数
}
while(node!=null){
if(node.val!=(stack.pop())){
return false;
}
node = node.next;
}
if(stack.isEmpty()){
return true;
}
return false;
}
}
JavaScript版本
/**
* @param {ListNode} head
* @return {boolean}
*/
var isPalindrome = function(head) {
let length = 0;
let node = head;
while(node!==null){
length++;
node = node.next;
}
node = head;
let stack = [];
for(let i=0;i<parseInt(length/2);i++){
stack.push(node);
node = node.next;
}
if(length%2===1){
node = node.next;
}
for(let i=0;i<parseInt(length/2);i++){
if(node.val!==stack.pop().val) return false;
node = node.next;
}
return true;
};
快慢指针法
先计算链表长度,将后半个链表反转,然后快指针从中间开始,慢指针从头开始一一对比,该方法虽然减小了空间复杂度,但需要修改原链表
- 时间复杂度:O(n)
- 空间复杂度:O(1)
Java版本
class Solution {
public boolean isPalindrome(ListNode head) {
if(head==null||head.next==null){
return true;
}
int len = 0;
ListNode node = head;
while(node!=null){
len++;
node = node.next;
}
node = head;
for(int i=0;i<len/2;i++){
node = node.next;
}
if(len%2!=0){
node = node.next;
}
ListNode pre = null;
ListNode next = null;
while(node!=null){
next = node.next;
node.next = pre;
pre = node;
node = next;
}
node = head;
while(pre!=null){
if(pre.val!=node.val){
return false;
}
pre = pre.next;
node = node.next;
}
return true;
}
}
class Solution {
public boolean isPalindrome(ListNode head) {
if(head==null||head.next==null) return true;
ListNode slow = head,fast = head;
//这个条件正好让slow停在第一半的最后一个节点,无论奇偶
while(fast.next!=null&&fast.next.next!=null){
slow = slow.next;
fast = fast.next.next;
}
ListNode head1 = reverse(slow.next);
slow = head;
fast = head1;
while(fast!=null){
if(slow.val!=fast.val) return false;
slow = slow.next;
fast = fast.next;
}
return true;
}
private ListNode reverse(ListNode head){
ListNode pre = null,node = head;
while(node!=null){
ListNode next = node.next;
node.next = pre;
pre = node;
node = next;
}
return pre;
}
}
JavaScript版本
/**
* @param {ListNode} head
* @return {boolean}
*/
var isPalindrome = function(head) {
let length = 0;
let node = head;
while(node!==null){
length++;
node = node.next;
}
node = head;
for(let i=0;i<parseInt(length/2);i++){
node = node.next;
}
if(length%2===1){
node = node.next;
}
let pre = null;
while(node!==null){
let next = node.next;
node.next = pre;
pre = node;
node = next;
}
node = head;
while(pre!==null){
if(pre.val!==node.val) return false;
pre = pre.next;
node = node.next;
}
return true;
};
分类:
LeetCode Hot100
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理