题目
给定一个链表的头节点head,请判断该链表是否为回文结构。
代码实现
public class IsPalindrome {
//需要O(N)额外空间
public boolean isPalindrome1(Node head) {
if (head == null || head.next == null) {
return true;
}
Stack<Node> stack = new Stack<>();
Node cur = head;
while (cur != null) { //将链表从左到右依次压入栈
stack.push(cur);
cur = cur.next;
}
while (head != null) {
if (head.value != stack.pop().value) {
return false;
}
head = head.next;
}
return true;
}
//需要O(N/2)额外空间
public boolean isPalindrome2(Node head) {
if (head == null || head.next ==null) {
return true;
}
Stack<Node> stack = new Stack<>();
Node right = head.next;
Node cur = head;
while (cur.next != null && cur.next.next != null) { //查找回文结构右半部分起点right
right = right.next;
cur = cur.next.next;
}
while (right != null) { //将回文结构的右半部分压入栈
stack.push(right);
right = right.next;
}
while (!stack.isEmpty()) {
if (stack.pop().value != head.value) {
return false;
}
head = head.next;
}
return true;
}
//不需要额外栈和其它数据结构
public 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; //n2->右部分第一个节点
n1.next = null; //mid.next->null
Node n3 = null;
while (n2 != null) { //右半区反转
n3 = n2.next; //n3->保存下一个节点
n2.next = n1; //下一个反转节点
n1 = n2; //n1移动
n2 = n3; //n2移动
}
n3 = n1; //n3->保存最后一个节点
n2 = head; //n2->左边第一个节点
boolean res = true;
while (n1 != null && n2 != null) { //检查回文
if (n1.value != n2.value) {
res = false;
break;
}
n1 = n1.next; //从左到中部
n2 = n2.next; //从右到中部
}
n1 = n3.next;
n3.next = null;
while (n1 != null) { //恢复列表
n2 = n1.next; //n2->保存下一个节点
n1.next = n3;
n3 = n1;
n1 = n2;
}
return res;
}
}