题目描述
给定一个链表的头结点,判断该链表是否是回文结构
样例
1->2->1 返回true
1->2->2->1 返回true
1->2->3 返回false
题解
方法一:
- 从左到右遍历链表,遍历的过程中将每个节点依次入栈
- 待所有节点入栈后,从栈顶到栈底中元素的值和链表中从左至右的值如果相等则证明是回文结构,否则不是
public static boolean isPalindrome(Node head) {
Stack<Node> stack=new Stack<>();
Node h=head;
while(h!=null) {
stack.push(h);
h=h.next;
}
h=head;
while(!stack.isEmpty()) {
if(stack.pop().value!=h.value) {
return false;
}
h=h.next;
}
return true;
}
方法二:
- 将链表拆分为左右两部分,只将右部分的元素入栈
例如:1->2->1 左部分为1右部分为1
1->2->2->1 左部分为1->2 右部分为2->1 - 只将右部分入栈,然后判断和左部分的值是否匹配
- 定位中间节点的办法:定义两个指针,一个快指针,一个慢指针,快指针每次走两步,慢指针每次走一步,快指针结束时,慢指针定位到右部分的第一个节点
public static boolean isPalindrome2(Node head) {
//如何找到中间节点,定义两个指针fast和slow,一个每次走两步,一次每次走一步
Node fast=head,slow=head.next;
while(fast.next!=null&&fast.next.next!=null) {
fast=fast.next.next;
slow=slow.next;
}
Stack<Node> stack=new Stack<>();
while(slow!=null) {
stack.push(slow);
slow=slow.next;
}
while(!stack.isEmpty()) {
if(stack.pop().value!=head.value) {
return false;
}
head=head.next;
}
return true;
}
方法三:
-
修改链表右半部分的结构,使其反转,然后令反转后的最后一个节点指向中间节点
-
左部分和右部分同时向中间节点移动,每移动一步判断值是否一样
-
最后将修改后的几个还原
public static boolean isPalindrome3(Node head) {
Node n1=head,n2=head;
while(n2.next!=null&&n2.next.next!=null) {
n2=n2.next.next;
n1=n1.next;
}
n2=n1.next;//右半部分的第一个节点;
n1.next=null;
Node n3=null;
while(n2!=null) {
n3=n2.next;
n2.next=n1;
n1=n2;
n2=n3;
}
n3=n1;//右半部分翻转后的头结点
n2=head;//左半部分的头结点
boolean re=true;
while(n1!=null&&n2!=null) {
if(n1.value!=n2.value) {
re=false;
break;
}
n1=n1.next;n2=n2.next;
}
//恢复链表
n1=n3.next;
n3.next=null;
while(n1!=null) {
n2=n1.next;
n1.next=n3;
n3=n1;
n1=n2;
}
return re;
}