【题目】
给定一个链表的头结点head,请判断该链表是否为回文结构。
【进阶】
时间复杂度O(N),额外空间复杂度达到O(1)
【代码】
//判断一个链表是否为回文结构
//方法1:利用栈结构,需要O(N)的空间
public static boolean isPalindrome1(Node head){
Stack<Node> stack=new Stack<Node>();
Node cur=head;
while(cur!=null){//链表从左到右依次压栈
stack.push(head);
cur=cur.next;
}
while(head!=null){
if(head.value!=stack.pop().value){
return false;
}
head=head.next;
}
return true;
}
//方法2:利用栈结构,需要O(N/2)的空间,压入右半区的节点
public static boolean isPalindrome2(Node head){
if(head==null||head.next==null){//有0个或1个节点
return true;
}
Node right=head.next;
Node cur=head;
//靠cur确定右半区起始点位置(right)
while(cur.next!=null&&cur.next.next!=null){
right=right.next;
cur=cur.next.next;
}
//把右半区压入栈
Stack<Node> stack=new Stack<Node>();
while(right!=null){
stack.push(right);
right=right.next;
}
//比较左半区和栈中弹出的值,如12321左半区12、右半区21压入栈后弹出顺序为12
while(!stack.isEmpty()){
if(head.value!=stack.pop().value){
return false;
}
head=head.next;
}
return true;
}
//方法3:改变链表右半区结构,使整个右半区反转,最后指向中间节点
public static boolean isPalindrome3(Node head){
if(head==null||head.next=null){
return true;
}
Node n1=head;
Node n2=head;
//查找中间节点
while(n2.next!=null && n2.next.next!=null){
n1=n1.next;//n1->中部
n2=n2.next.next;//n2->结尾
}
n2=n1.next;//右部分第一个节点
n1.next=null;//使中间节点指向null
Node n3=null;
while(n2!=null){//反转右半区
n3=n2.next;//保存后一个节点
n2.next=n1;//右边第一个节点指向中间节点
n1=n2;//右移,最后n1到达右边末尾
n2=n3;
}
n3=n1;//保存最后一个节点
n2=head;//左边第一个节点
boolean res=true;
//检查回文
while(n1!=null&&n2!=null){
if(n1.value!=n2.value){
res=false;
break;
}
n1=n1.next;//右到中
n2=n2.next;//左到中
}
n1=n3;//不明白原文答案n1=n3.next?
n3=null;//不明白原文答案n3.next=null?
//无论结果是不是回文,都要恢复链表
while(n1!=null){
n2=n1.next;//保存左边一个节点
n1.next=n3;
n3=n1;
n1=n2;//左移,从右到中恢复
}
}
本文介绍三种判断链表是否为回文结构的方法:使用栈结构、仅压入右半区节点到栈、反转右半区并指向中间节点。每种方法都提供了详细代码实现,并讨论了时间与空间复杂度。
1957

被折叠的 条评论
为什么被折叠?



