Given a singly linked list, determine if it is a palindrome.
Follow up:
Could you do it in O(n) time and O(1) space?
1. 获取链表的中点,使用龟兔算法的方法,两个指针,一个遍历速度是另外一个的两倍,找到中点
2. 从中间节点的下一个节点开始,反转链表
3. 对比链表的前后两个部分是否一样
package leetcode;
public class Palindrome_Linked_List_234 {
public boolean isPalindrome(ListNode head) {
if(head==null){
return true;
}
ListNode middle=getMiddle(head);//找到链表的中间节点(看下方的解释,注意此处getMiddle的特点)
ListNode rightHead=middle.next; 从链表中点的下一个节点开始,反转链表
ListNode rightReverse=reverse(rightHead);
while(rightReverse!=null){//右半段的长度<=左半段的长度(因为若有奇数个结点,中间节点被放在左半段)
if(rightReverse.val!=head.val){
return false;
}
else{
head=head.next;
rightReverse=rightReverse.next;
}
}
return true;
}
public ListNode reverse(ListNode head){
ListNode rHead=null;// 反转后链表的头结点,先初始化为NULL
ListNode now=head;// 让当前节点指向第一个节点
ListNode pre=null;
while(now!=null){
ListNode next=now.next;
if(next==null){
rHead=now;
}
now.next=pre;
pre=now;
now=next;
}
return rHead;
}
public ListNode getMiddle(ListNode head){//1->2->3->4->3->2-1
ListNode fast=head;
ListNode slow=head;
while(fast!=null&&fast.next!=null&&fast.next.next!=null){
fast=fast.next.next;
slow=slow.next;
}
return slow;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Palindrome_Linked_List_234 p=new Palindrome_Linked_List_234();
ListNode head=new ListNode(1);
head.next=new ListNode(2);
head.next.next=new ListNode(3);
head.next.next.next=new ListNode(3);
head.next.next.next.next=new ListNode(2);
head.next.next.next.next.next=new ListNode(1);
System.out.println(p.isPalindrome(head));
}
}
需要注意的是:
备注:关于单链表的中间节点问题,详见博文“寻找单链表的中间节点“。
有一个注意点如下: