234.回文链表
快慢指针:
将链表的后半部分反转(改变链表结构),然后将前半部分和后半部分进行比较。比较完成后我们应该将链表恢复原样。虽然不需要恢复也能通过测试用例
使用快慢指针在一次遍历中找到链表的中间位置:慢指针一次走一步,快指针一次走两步,快慢指针同时出发。当快指针移动到链表的末尾时,慢指针恰好到链表的中间。通过慢指针将链表分为两部分。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
if(head == null){
return true;
}
//找到前半部分链表的尾节点并反转后半部分链表
ListNode firstHalfEnd = endOfFirstHalf(head);
ListNode secondHalfStart = reverseList(firstHalfEnd.next);
//判断是否是回文
ListNode p1 = head;
ListNode p2 = secondHalfStart;
boolean result = true;
while(result && p2 != null){
if(p1.val != p2.val){
result = false;
}
p1 = p1.next;
p2 = p2.next;
}
//还原链表并返回结果
firstHalfEnd.next = reverseList(secondHalfStart);
return result;
}
//翻转链表
private ListNode reverseList(ListNode head){
ListNode pre = null;
ListNode cur = head;
while(cur!=null){
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
//使用快慢指针找到链表中间的位置
private ListNode endOfFirstHalf(ListNode head){
ListNode fast = head;
ListNode slow = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
}