题目描述
给你一个单链表的头节点
head
,请你判断该链表是否为回文链表。如果是,返回true
;否则,返回false
。示例 1:
输入:head = [1,2,2,1] 输出:true示例 2:
输入:head = [1,2] 输出:false提示:
- 链表中节点数目在范围
[1, 105]
内0 <= Node.val <= 9
进阶:你能否用
O(n)
时间复杂度和O(1)
空间复杂度解决此题?
解题思路
-
快慢指针找到中间节点: 使用快慢指针方法,快指针每次移动两个节点,慢指针每次移动一个节点。当快指针到达链表末尾时,慢指针正好处于链表的中间节点。
-
反转链表的后半部分: 从中间节点开始,反转链表的后半部分。这一步可以用来比较链表的前半部分和反转后的后半部分。
-
比较两个半部分: 比较链表的前半部分和反转后的后半部分。如果它们相同,那么链表是回文的。
-
恢复链表的原始状态: 为了保持链表的原始结构,可以在比较完成后再次反转链表的后半部分,恢复链表的结构。
复杂度分析
- 时间复杂度: O(n)。需要遍历链表几次,每次遍历的时间复杂度是 O(n)。
- 空间复杂度: O(1)。只使用了常数级的额外空间(指针变量),没有使用额外的存储结构。
代码实现
package org.zyf.javabasic.letcode.hot100.list;
import org.zyf.javabasic.letcode.list.base.ListNode;
/**
* @program: zyfboot-javabasic
* @description: 回文链表
* @author: zhangyanfeng
* @create: 2024-08-22 00:03
**/
public class PalindromeSolution {
public boolean isPalindrome(ListNode head) {
if (head == null || head.next == null) {
return true; // 空链表或只有一个节点的链表是回文的
}
// 快慢指针找到链表的中间
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// 反转链表的后半部分
ListNode secondHalf = reverseList(slow);
ListNode firstHalf = head;
// 比较前半部分和后半部分
while (secondHalf != null) {
if (firstHalf.val != secondHalf.val) {
return false;
}
firstHalf = firstHalf.next;
secondHalf = secondHalf.next;
}
// 恢复链表的原始状态
reverseList(slow);
return true;
}
// 反转链表的函数
private ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
public static void main(String[] args) {
PalindromeSolution solution = new PalindromeSolution();
// 测试用例 1: 回文链表
System.out.println("Test Case 1: [1, 2, 2, 1]");
ListNode head1 = new ListNode(1);
head1.next = new ListNode(2);
head1.next.next = new ListNode(2);
head1.next.next.next = new ListNode(1);
System.out.println("Is palindrome: " + solution.isPalindrome(head1));
// 测试用例 2: 非回文链表
System.out.println("Test Case 2: [1, 2]");
ListNode head2 = new ListNode(1);
head2.next = new ListNode(2);
System.out.println("Is palindrome: " + solution.isPalindrome(head2));
// 测试用例 3: 单节点链表
System.out.println("Test Case 3: [1]");
ListNode head3 = new ListNode(1);
System.out.println("Is palindrome: " + solution.isPalindrome(head3));
// 测试用例 4: 空链表
System.out.println("Test Case 4: []");
ListNode head4 = null;
System.out.println("Is palindrome: " + solution.isPalindrome(head4));
}
}
具体可参考:https://zyfcodes.blog.csdn.net/article/details/141401712