234.回文链表

234.回文链表

题目

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。

image

示例1

输入:head = [1,2,2,1]
输出:true

示例2
image

输入: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;

image

posted @ 2021-12-15 16:15  rananie  阅读(29)  评论(0编辑  收藏  举报