
所谓回文,就是从前往后读和从后往前读都一样,比如 1→2→3→2→1 就是回文链表。
代码逻辑
1.找到链表的中点
java
ListNode slow = head, fast = head;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
这里判断条件是 fast.next != null && fast.next.next != null
,能保证 slow 最终停在中间偏左的位置,无论链表长度是奇数还是偶数都适用。
2.翻转后半部分链表
从中点开始,把后半部分链表反转。
反转后,链表变成了一个"双向箭头"的结构:前半部分从 head 指向中点,后半部分从尾部指向中点。
java
ListNode pre = slow;
ListNode cur = pre.next;
ListNode next = null;
pre.next = null; // 断开前后两部分
while (cur != null) {
next = cur.next; // 保存下一个节点
cur.next = pre; // 反转指针
pre = cur; // pre 前进
cur = next; // cur 前进
}
3.双指针比对值
现在有两个指针:left
从头开始往右走,right
从尾开始往左走。
每一步比对两个节点的值,如果不相等就说明不是回文。
java
boolean ans = true;
ListNode left = head;
ListNode right = pre;
while (left != null && right != null) {
if (left.val != right.val) {
ans = false;
break;
}
left = left.next;
right = right.next;
}
4.恢复链表原状
判断完成后,不能把链表留成反转的状态,需要把后半部分再翻转回去。
java
cur = pre.next;
pre.next = null;
while (cur != null) {
next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
完整代码
java
public static boolean isPalindrome(ListNode head) {
if (head == null || head.next == null) {
return true;
}
ListNode slow = head, fast = head;
// 找中点
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// 翻转后半部分
ListNode pre = slow;
ListNode cur = pre.next;
ListNode next = null;
pre.next = null;
while (cur != null) {
next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
// 双指针比对
boolean ans = true;
ListNode left = head;
ListNode right = pre;
while (left != null && right != null) {
if (left.val != right.val) {
ans = false;
break;
}
left = left.next;
right = right.next;
}
// 恢复链表
cur = pre.next;
pre.next = null;
while (cur != null) {
next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return ans;
}