234.回文链表
234.回文链表
题目
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。
示例1
输入:head = [1,2,2,1]
输出:true
示例2
输入:head = [1,2]
输出:false
进阶:你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
题解
回文:abba,或者aba对称的模式
一个最简单的思路就是翻转链表之后,比较对应位置是否相同。
这样需要新建一个链表,也就是原链表的翻转链表。这样空间复杂度就不是1了。
可以不新建链表吗?可以把原链表分成两部分,一部分翻转,一部分不翻转,然后开始比较。
翻转链表
ListNode reverseList(ListNode head){
ListNode pre=null;
ListNode tmp;
while(head != null){
tmp=head.next;
head.next = pre;
pre=head;
head=tmp;
}
return pre;
}
需要将链表分成两部分,需要使用双指针
- 情况1:abba slow指向的第一个b,fast指向的最后一个元素,需要翻转ab
- 情况2:aba slow指向b,fast执行null,需要反转a
//如果只有一个元素直接返回不用反转
if(head.next==null) return true;
//把链表分成两个部分,
ListNode slow = head;
ListNode fast = head.next;
while(fast!=null && fast.next!=null){
slow = slow.next;
fast=fast.next.next;
}
//反转链表 abba->abab babab->babba
slow.next = reverseList(slow.next); //参数slow.next指向需要反转的链表
fast = slow.next; //fast指向第二段链表的开头
//开始判断是否是回文
while(fast!=null){
if(head.val != fast.val)return false;
head = head.next;
fast = fast.next;
}
return true;
代码
class Solution {
public boolean isPalindrome(ListNode head) {
if(head.next==null) return true;
ListNode slow = head;
ListNode fast = head.next;
//找到中间位置
while(fast!=null && fast.next!=null){
slow = slow.next;
fast=fast.next.next;
}
//后面的反转
slow.next = reverseList(slow.next);
fast = slow.next;
//开始判断是否是回文
while(fast!=null){
if(head.val != fast.val)return false;
head = head.next;
fast = fast.next;
}
return true;
}
//反转链表
ListNode reverseList(ListNode head){
ListNode pre=null;
ListNode tmp;
while(head != null){
tmp=head.next;
head.next = pre;
pre=head;
head=tmp;
}
return pre;
}
}
优化
这里我们反转的是中点后面的链表,并且后面的位置我们已经遍历过了。
可不可以边找中点的时候,边反转前面的链表?这样走过的链表就不用再走了
if(head.next==null) return true;
ListNode slow = head;
ListNode fast = head;
ListNode pre = null;
ListNode tmp = head; //反转时使用
//找到中间位置
while(fast!=null && fast.next!=null){
fast=fast.next.next; //fast先行,防止反转后找不到位置。
tmp =slow.next;
slow.next = pre;
pre = slow;
slow = tmp;
}
//退出的时候,如下图所示:情况1的slow需要再走一步进行比较
if(fast!=null) slow=slow.next;
while(slow!=null){
if(pre.val!=slow.val) return false;
pre = pre.next;
slow = slow.next;
}
return true;