1.题目描述
给定一个链表的 头节点 head ,请判断其是否为回文链表。
如果一个链表是回文,那么链表节点序列从前往后看和从后往前看是相同的。
示例 1:
输入: head = [1,2,3,3,2,1]
输出: true
示例 2:
输入: head = [1,2]
输出: false
2.解题思路与代码
2.1 解题思路
这道题我们可以先找到链表的中点,然后再根据中点将链表截断,将截断后的后半部分链表进行反转,然后再使用反转后的后半部分链表与原链表进行比较。根据这个思路我们首先需要找到链表的中点,使用快慢指针的方式找到中点位置。快指针 fast 每次移动两步,慢指针 slow 每次移动一步,直到快指针 fast 等于 null 或者 fast.next 等于 null 为止,此时的 slow 所指位置便是中点。有人也许会问此时链表长度为奇数和偶数会出现两种情况,其实链表节点个数为基数或者偶数其实结果是一样的。下面图片分别展示链表个数是奇数和偶数两种情况下的快慢指针重点情况。
可以看到当链表节点个数为奇数的时候正好取到中间位置,此时后半部分为 3->2->1,前半部分为 1->2->3,此时反转后半部分便能够判断链表是否是回文。链表节点个数为偶数的中点如下:
此时 slow 指向中间两个节点的后一个节点,后半部分为 2->1 前半部分为 1->2,正好满足。
在获取到中点后,便可以对后半部分链表进行反转,然后将原链表和反转后的链表依次比较节点值,如果不同返回 false,直到比较完成。
2.2 代码
class Solution {
public boolean isPalindrome(ListNode head) {
// 利用快慢指针查找链表中点
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
// 反转后半部分链表
ListNode reverse = reverse(slow);
// 前后两部分链表依次进行比较
while (reverse != null) {
if (head.val != reverse.val) {
return false;
}
head = head.next;
reverse = reverse.next;
}
return true;
}
private ListNode reverse(ListNode head) {
ListNode next = null;
ListNode pre = null;
ListNode curr = head;
while (curr != null) {
next = curr.next;
curr.next = pre;
pre = curr;
curr = next;
}
return pre;
}
}
2.3 测试结果
通过测试
3.总结
- 首先使用快慢指针找到链表中点
- 反转后半部分链表,然后再与前半部分链表依次比较