题目描述
请判断一个链表是否为回文链表。
样例描述
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
/**
* 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 firstHalfTail = tailOfFirstHalf(head);
ListNode secondHalfStart = reverseList(firstHalfTail.next);
//判断是否回文
ListNode p1 = head;
ListNode p2 = secondHalfStart;
boolean ans = true;
//只用考虑后半部分走到空就行 比较时前半部分不会走到空
while (ans && p2 != null){
if (p1.val != p2.val){
ans = false;
}
p1 = p1.next;
p2 = p2.next;
}
//还原链表同时返回结果
firstHalfTail.next = reverseList(secondHalfStart);
return ans;
}
private ListNode reverseList(ListNode head){
if (head == null) return head;
ListNode p = head, q = head.next;
while (q != null){
ListNode r = q.next;
q.next = p;
p = q;
q = r;
}
//逆序后,记得让原来头结点指向空
head.next = null;
//返回的是反转后链表的头结点,也就是原来链表的尾结点
return p;
}
//寻找中点,也就是第一个链表的尾结点,快慢指针法
private ListNode tailOfFirstHalf(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;
}
}