234. Palindrome Linked List
Leetcode Linked List Two PointersGiven a singly linked list, determine if it is a palindrome.
Example 1:
Input: 1->2
Output: false
Example 2:
Input: 1->2->2->1
Output: true
Follow up: Could you do it in O(n) time and O(1) space?
package com.leetcode;
/**
* An Palindrome is a sequence of characters
* which reads the same backward or forward.
*
*
* 这道题目第一让人联想到的就是Leetcode Q206ReverseLinkedList,
* 即将链表反转,然后一一比对。
*
* 在这里,只要将链表的后半部分反转,然后利用两个指针分别指向链表首尾,
* 依次向前/向后移动指针,直到到达中点。
*
* 我觉得这里的难点主要是要考虑一些特殊情况,比如说只有2,3个元素的这种链表。
*
*/
public class Q234PalindromeLinkedList {
public static boolean isPalindrome(ListNode head) {
if ((head == null) || (head.next == null)) {
return true;
}
// find lenth
int len;
ListNode pos = head;
for (len = 0; pos != null; len++) {
pos = pos.next;
}
// find middle node
ListNode mid = head;
for (int i = 0; i < (len-1)/2; i++)
mid = mid.next;
// reverse
ListNode cur = mid.next;
if (cur.next != null) {
ListNode next;
for (pos = mid; cur.next != null; ) {
next = cur.next;
cur.next = pos;
pos = cur;
cur = next;
}
cur.next = pos;
} else {
cur.next = mid;
}
ListNode tail = cur;
// compare the first and second half nodes
while (tail != mid) {
if (tail.val != head.val) {
return false;
}
tail = tail.next;
head = head.next;
}
return true;
}
/**
* 寻找mid和tail时其实不用计算链表长度
* 只要有两个指针,一块一慢,遍历链表即可
*/
public static boolean isPalindromeUsingQuickFindMidTail(ListNode head) {
if ((head == null) || (head.next == null)) {
return true;
}
// A trick to quickly find mid and tail of linked list
ListNode mid = head, tail = head.next;
while ((tail != null) && (tail.next != null)) {
mid = mid.next;
tail = tail.next.next;
}
// reverse
ListNode cur = mid.next, pos, next;
if (cur.next != null) {
for (pos = mid; cur.next != null; ) {
next = cur.next;
cur.next = pos;
pos = cur;
cur = next;
}
cur.next = pos;
} else {
cur.next = mid;
}
tail = cur;
// compare the first and second half nodes
while (tail != mid) {
if (tail.val != head.val) {
return false;
}
tail = tail.next;
head = head.next;
}
return true;
}
}