1.题目描述
2.思路
(1)将链表取中位数,分为左右两部分。
(2)右半部分的元素进行反转链表,能达到O(1)的空间复杂度
(3)再判断左右部分的元素,是否相等。如果相等,则是回文字符串
3.代码实现
/**
* 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;
//1.创建快慢指针,都从头节点出发
ListNode slow=head;
ListNode fast=head;
//2.用快慢指针找中点, 访问指针前必须判断当前指针和下一个指针是否为 null,防止空指针异常。
while(fast!=null&&fast.next!=null)
{
slow=slow.next;// 走一步
fast=fast.next.next; // 走两步
//如果是偶数,慢指针会停留在前半部分的尾数上
//如果是奇数,慢指针中位数上
}
// 第二步:反转后半部分链表(从 slow 开始)
ListNode backHalf=reverseList(slow);
// 第三步:从头和反转后的中点开始比较
ListNode p1=head;
ListNode p2=backHalf;
while(p2!=null&&p1!=null)
{
if(p2.val!=p1.val)//你只判断了 p2 != null,但 p1 可能提前变成了 null(尤其链表长度是奇数时)
{
return false;
}
p1=p1.next;
p2=p2.next;
}
return true;
}
// 辅助函数:反转链表
private ListNode reverseList(ListNode head) {
ListNode pre=null;
ListNode curr=head;
while(curr!=null)//while(curr != null),这样最后一个节点才能反转。
{
ListNode temp=curr.next;//暂存第二个节点
//赋值,修改指针引用(现在==过去)。反转指针方向
curr.next=pre;
//整体移动指针,先移动指针,再移动值(继续下一个节点)
pre=curr;
curr=temp;
}
return pre;//指向的就是 反转后的新头节点
}
}