234.回文链表
给你一个单链表的头节点 head
,请你判断该链表是否为回文链表。如果是,返回 true
;否则,返回 false
。
示例 1:
输入:head = [1,2,2,1] 输出:true
示例 2:
输入:head = [1,2] 输出:false
提示:
- 链表中节点数目在范围
[1, 10^5]
内 0 <= Node.val <= 9
解题思路
- 快慢指针找中点:
- 快指针每次移动两步,慢指针每次移动一步
- 当快指针到达链表末尾,慢指针位于链表中点
- 反转后半部分链表:
- 从中点的下一个节点开始反转链表
- 比较前后部分:
- 使用两个指针分别从头节点和反转后的后半部分的头结点开始,逐个节点比较值
- 如果所有值相等,则是回文链表,否则不是
实现代码
/**
* 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 || head.next == null){
return true;
}
//使用快慢指针找到链表中点
ListNode slow = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null){
slow = slow.next;
fast = fast.next.next;
}
//反转后半部分列表
ListNode secondHalfStart = reverseList(slow.next);
//比较前半部分和反转后的后半部分
ListNode p1 = head;
ListNode p2 = secondHalfStart;
boolean result = true;
while(p2 != null){
if(p1.val != p2.val){
result = false;
break;
}
p1 = p1.next;
p2 = p2.next;
}
return result;
}
// 反转链表
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
}
代码解释
//处理链表的边界值情况
if (head == null || head.next == null) {
return true;
}
- head == null:
- 如果传入的链表头结点head为null,说明链表为空
- 空链表本身就是一个回文链表,因此直接返回true
- head.next == null:
- 如果链表只有一个节点(head.next = null),说明链表只有一个元素
- 单个节点的链表也是回文链表,因此直接返回true
reverseList()方法
// 反转链表
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
- 初始化prev为null,curr为头节点
- 遍历链表,将当前节点的next指向prev,然后更新prev和curr
- 返回反转后的头节点prev