请判断一个链表是否为回文链表。
示例 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(int x) { val = x; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
if (head == null) {
return true;
}
ListNode middleNode = findMiddle(head); // 1. 寻找链表中间节点
middleNode.next = reverse(middleNode.next); // 2. 通过中间节点,将后半部分反转
// 3. 逐个比较
ListNode p1 = head, p2 = middleNode.next;
while (p1 != null && p2 != null && p1.val == p2.val) {
p1 = p1.next;
p2 = p2.next;
}
return p2 == null;
}
/* 寻找链表中间节点 */
private ListNode findMiddle(ListNode head) {
if (head == null) {
return null;
}
ListNode slow = head, fast = head.next;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
/* 通过中间节点,将后半部分反转 */
private ListNode reverse(ListNode head) {
if (head == null) {
return null;
}
ListNode prev = null;
while (head != null) {
ListNode temp = head.next;
head.next = prev;
prev = head;
head = temp;
}
return prev;
}
}