题解一:
双指针数组:将链表存储在数组中,通过双指针双向访问数组进行比较。
import java.util.ArrayList;
class Solution {
public boolean isPalindrome(ListNode head) {
ArrayList<ListNode> list = new ArrayList<>();
while (head != null) {
list.add(head);
head = head.next;
}
for (int i = 0, j = list.size() - 1; i < j; i++, j--) {
if (list.get(i).val != list.get(j).val) return false;
}
return true;
}
}
题解二:
迭代+递归:通过迭代正向遍历链表,通过递归逆向遍历链表,同时进行比较。
class Solution {
private ListNode front;
public boolean F(ListNode head) {
if (head.next != null)
if(!F(head.next))return false;
if (front.val != head.val) {
return false;
}
front = front.next;
return true;
}
public boolean isPalindrome(ListNode head) {
front = head;
return F(head);
}
}
题解三:
链表反转:将回文前半部分反转,此时前半部分与后半部分一致。利用这一特点我们可以反转链表的前半部分,再将前半部分与后半部分比较,一致则是回文。通过快慢指针可以定位到链表中部,快指针走两步,慢指针走一步,则快指针到达末尾时慢指针恰好到达中部。
有两点需要注意:第一,当节点个数为奇数时,慢指针slow恰好定位到中间节点,但中间节点不进行比较,所以slow=slow.next;当节点个数为偶数是,慢指针slow定位到右半段第一位节点。第二,翻转左半段时只是改变指针指向,最后head需要定位到左半段翻转后的第一位也就是原先位于slow左边的节点。
class Solution {
public boolean isPalindrome(ListNode head) {
if(head.next==null)return true;//特判仅一个节点
ListNode slow = head;//快慢指针找中点
ListNode quick = head;
while (quick != null && quick.next != null) {
quick = quick.next.next;
slow = slow.next;
}
ListNode pre = null;//翻转前半部分链表,最后定位到slow左一位节点
while (true) {
ListNode temp = head.next;
head.next = pre;
pre = head;
if (temp == slow) break;
head = temp;
}
if (quick != null) {//有奇数个节点时,中间节点不参加比较
slow = slow.next;
}
while (slow != null) {//前后部分比较
if (slow.val != head.val) return false;
slow = slow.next;
head = head.next;
}
return true;
}
}