题目描述
给你一个单链表的头节点 head
,请你判断该链表是否为回文链表。如果是,返回 true
;否则,返回 false
示例 1:

输入:head = [1,2,2,1]
输出:true
示例 2:

输入:head = [1,2]
输出:false
解题思路
1.栈+双指针
大致思路:使用双指针定位中心元素并将链表前半部分入栈,挨个出栈并遍历后半部分做比较,如果不想等则为false;
java
class Solution {
public boolean isPalindrome(ListNode head) {
if (head == null || head.next == null) {
return true;
}
// 使用快慢指针找到链表中点
ListNode slow = head;
ListNode fast = head;
LinkedListStack<Integer> stack = new LinkedListStack<>();
// 将前半部分入栈
while (fast != null && fast.next != null) {
stack.push(slow.val);
slow = slow.next;
fast = fast.next.next;
}
// 如果链表长度是奇数,跳过中间节点
if (fast != null) {
slow = slow.next;
}
// 比较后半部分和栈中元素
while (slow != null) {
if (stack.pop() != slow.val) {
return false;
}
slow = slow.next;
}
return true;
}
}
public class LinkedListStack<T> {
// 定义链表节点
private static class Node<T> {
T data;
Node<T> next;
Node(T data) {
this.data = data;
this.next = null;
}
}
private Node<T> top; // 栈顶节点
private int size; // 栈的大小
public LinkedListStack() {
top = null;
size = 0;
}
// 入栈操作
public void push(T item) {
Node<T> newNode = new Node<>(item);
newNode.next = top; // 新节点的next指向原来的栈顶
top = newNode; // 更新栈顶为新节点
size++;
}
// 出栈操作
public T pop() {
if (isEmpty()) {
throw new IllegalStateException("Stack is empty");
}
T item = top.data; // 获取栈顶数据
top = top.next; // 栈顶指向下一个节点
size--;
return item;
}
// 判断栈是否为空
public boolean isEmpty() {
return top == null;
}
}
2.反转链表+双指针
java
class Solution {
public boolean isPalindrome(ListNode head) {
if (head == null || head.next == null) return true;
// 1. 快慢指针找中点
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// 2. 反转后半部分
ListNode reversedSecondHalf = reverse(slow);
// 3. 比较前后两部分
ListNode p1 = head, p2 = reversedSecondHalf;
boolean isPalindrome = true;
while (p2 != null) {
if (p1.val != p2.val) {
isPalindrome = false;
break;
}
p1 = p1.next;
p2 = p2.next;
}
return isPalindrome;
}
private ListNode reverse(ListNode head) {
//prev指向反转后链表的最后一个 初始为null curr指向要反转的那个节点,从head开始
ListNode prev = null, curr = head;
while (curr != null) {
//将反转的下一个节点先记录下来
ListNode next = curr.next;
//使用头插法
curr.next = prev;
//将当前反转的节点设置为反转后节点的最后一个
prev = curr;
//反转下一个节点
curr = next;
}
return prev;
}
}