题目
https://leetcode-cn.com/problems/palindrome-linked-list/
请判断一个链表是否为回文链表。
分析
将链表的后半部分反转,然后比较前半部分和后半部分。如果有奇数个节点,则中间的节点应该看作是前半部分。
步骤:
1.使用快慢指针,找到前半部分的尾节点
2.反转后半部分链表。
3.比较两个部分的值,当后半部分到达末尾则比较完成,可以忽略计数情况中的中间节点。
4.恢复链表(再反转一次,同2)
5.返回结果
//另外,最后应将链表恢复原样。虽然不恢复也能通过测试用例,但使用该函数的人通常不希望链表结构被更改。
代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
if(head==null||head.next==null)
return true;
ListNode fast=head,slow=head;
while(fast.next!=null&&fast.next.next!=null){
slow=slow.next;
fast=fast.next.next;
}
//slow就是中间节点
ListNode later=slow.next;
later=reverse(later);//获取反转后的 后半部分的头结点
//ListNode later1=later; 保存这个节点用于恢复
//判断回文
while(later!=null){
if(head.val!=later.val)
return false;
head=head.next;
later=later.next;
}
//reverse(later1);恢复
return true;
}
//反转链表
private ListNode reverse(ListNode head){
ListNode tmp=null;
ListNode pre=null;
while(head!=null){
tmp=head.next;
head.next=pre;
pre=head;
head=tmp;
}
return pre;
}
}
复杂度
时间复杂度:O(n),其中 n 指的是链表的大小。
空间复杂度:O(1)。我们只会修改原本链表中节点的指向,而在堆栈上的堆栈帧不超过 O(1)。