1. Description
Given the head of a singly linked list, return true if it is a palindrome.
Follow up: Could you do it in O(n) time and O(1) space?
请判断一个链表是否为回文链表。

2. Analysis
- 链表不好判断回文的原因是链表指针的单向性,无法获得前驱结点。故本题第一反应将链表整个反转后与原链表进行比较,但此方法产生了一条与原链表长度相等的新链表,不满足O(1)空间复杂度。
- 既然不能产生大小为n的新的存储空间,能否直接在原链表上进行反转操作后进行回文判断?答案是肯定的,我们只需要反转链表的后半部分,再比较链表的前半部分和后半部分即可。
- 要想反转后半部分,需要使用快慢指针找到中间节点,反转操作和比较操作较为简单,这里不加赘述。
- 快慢指针:
3. Code
class Solution{
public boolean isPalindrome(ListNode head){
// 快慢指针找到链表中点
ListNode fast, slow;
fast = slow = head;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
}
// 奇数情况slow再移一步
if(fast != null) slow = slow.next;
// 反转从slow开始的链表
ListNode right = reverse(slow);
ListNode left = head;
// 对两段链表进行比较
while(right != null){
if(left.val != right.val) return false;
left = left.next;
right = right.next;
}
return true;
}
/*
反转以head为头节点的链表并返回新链表的头节点
*/
private ListNode reverse(ListNode head){
ListNode prev = null, cur = head;
ListNode nxt = head;
while(cur != null){
nxt = cur.next;
cur.next = prev;
prev = cur;
cur = nxt;
}
return prev;
}
}
4. Complexity
- Time:未出现循环的嵌套,出现了对链表的遍历,O(n)
- Space:未开辟链表长度大小的存储空间,只使用了常数个变量,O(1)
5. Summary
- 本题核心在于找到中间节点(快慢指针),反转后半部分,比较前半部分和反转后的后半部分