//方法一,利用一个栈
public boolean isPalindrome(Node head){
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;
}
方法二,对方法一的优化,同样利用栈结构,压入一半的节点
public boolean isPalindrome1(Node head){
if (head==null || head.next==null) return true;
//这两行是核心代码,找到右半区的首节点,每增加两个节点,右半区节点右移一位
Node right = head.next,cur = head;
while (cur.next!=null && cur.next.next!=null){
cur = cur.next.next;
//slow -> 右半区第一个节点
right = right.next;
}
Stack<Node> stack = new Stack<>();
while (right!=null){
stack.push(right);
right = right.next;
}
while (!stack.isEmpty()){
if (head.value!=stack.pop().value) return false;
head = head.next;
}
return true;
}
方法三,利用几个变量,在空间复杂度O(1)内完成
public boolean isPalindrome2(Node head){
if (head==null || head.next==null) return true;
Node n1 = head,n2 = head;
//找到中间节点
while (n2.next!=null && n2.next.next!=null){
//中间
n1 = n1.next;
//倒数第二个或第一个节点
n2 = n2.next.next;
}
//右部分第一个节点
n2 = n1.next;
//mid.next -> null
n1.next = null;
Node n3 = null;
//右半区进行反转
while (n2!=null){
n3 = n2.next;
n2.next = n1;
n1 = n2;
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.next;
n3.next = null;
while (n1!=null){
n2 = n1.next;
n1.next = n3;
n3 = n1;
n1 = n2;
}
return res;
}
测试
public static void main(String[] args) {
Node head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(3);
head.next.next.next= new Node(3);
head.next.next.next.next = new Node(1);
boolean result = isPalindrome1(head);
System.out.println(result);
}