方法1:自己实现
- 找到中间节点
- 用栈空间判断是否回文
package com.company.linked;
import java.util.Stack;
public class Solution8 {
public boolean isPalindrome(ListNode head) {
ListNode fast = new ListNode(0, head);
ListNode slow = new ListNode(0, head);
Stack<ListNode> stack = new Stack<>();
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
stack.push(slow);
}
//链表长度偶数
if (fast != null && fast.next == null) {
slow = slow.next;
while (slow != null && stack.peek().val == slow.val) {
stack.pop();
slow = slow.next;
}
if (stack.isEmpty()) {
return true;
}
return false;
}
//链表长度奇数
if (fast == null) {
while (slow != null && stack.peek().val == slow.val) {
stack.pop();
slow = slow.next;
}
if (stack.isEmpty()) {
return true;
}
return false;
}
return false;
}
}
方法2:将数值复制到数组,用双指针判断回文
方法3:快慢指针找到中间节点,将后半部分反转,判断回文
- 不需要额外的空间
- 反转链表后需要将链表再恢复,也可以不恢复,不恢复破坏了数据结构
- 并发问题,反转链表后有其它链表操作则存在问题
package com.company.linked;
public class Solution8_2 {
public boolean isPalindrome(ListNode head) {
if (head == null) {
return true;
}
// 找到前半部分链表的尾节点并反转后半部分链表
ListNode firstHalfEnd = endOfFirstHalf(head);
ListNode secondHalfStart = reverseList(firstHalfEnd.next);
// 判断是否回文
ListNode p1 = head;
ListNode p2 = secondHalfStart;
boolean result = true;
while (result && p2 != null) {
if (p1.val != p2.val) {
result = false;
}
p1 = p1.next;
p2 = p2.next;
}
// 还原链表并返回结果
firstHalfEnd.next = reverseList(secondHalfStart);
return result;
}
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;
}
private ListNode endOfFirstHalf(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
}
思考总结:
- 主要考核
- 快慢指针找中间点问题
- 双指针遍历链表模板代码
- 链表反转
- 回文链表的定义