链表的回文结构(简单难度)

题目概述(简单难度)

对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。
给定一个链表的头指针A,请返回一个boolean值,代表其是否为回文结构。保证链表长度小于等于900。

示例 1:

输入: 1->2
输出: false

示例 2:

输入: 1->2->2->1
输出: true

在此附上牛客网和leetcode的题目链接:
点击此处进入leetcode
点击此处进入牛客网

思路与代码

思路展现

回文结构

这道题目是需要我们判断一个链表是否为回文结构,那么首先我们来了解下什么是回文结构吧:

反转之后还是与原链表一样,就是回文结构。

那么对于一个奇数链表和偶数链表(这里的奇偶数指的就是链表中节点的个数)而言,都是存在回文链表的:举个例子:

奇数链表:24->12->78->12->24
偶数链表:24->12->12->24

因为有了不同的情况,我们的代码就必须将两种情况全部兼顾:

核心思路

对于回文链表的思路是这样的:
1:找到链表的中间节点,奇数链表和偶数链表的中间节点各不相同,这里我们使用快慢指针的方法,如果有小伙伴忘了快慢指针是如何找到的,可以参考我之前的博客链接:
点击此处进入博客
2:从中间节点后一个节点开始到尾节点全部进行反转。反转的思路可以参考我之前的博客,使用的是迭代法,这里就不再进行过多的赘述:
点击此处进入博客
3:反转完毕后,分别同时头节点尾节点开始遍历链表,然后判断节点对应的值域是否相同,相同返回true,说明是回文链表,不相同返回false,说明不是回文链表,当然这里对于偶数链表来说还有一个特殊情况,我们待会再来根据代码和图进行分析.

代码示例

class Solution {
    public boolean isPalindrome(ListNode head) {
       //链表为空的情况
        if(head==null){
            return false;  
        }
         ListNode slow=head;
         ListNode fast=head;
         
         //寻找中间节点
         while(fast!=null&&fast.next!=null){
             slow=slow.next;
             fast=fast.next.next;
         }
        
        //反转链表
         ListNode cur=slow.next;
         while(cur!=null){
             ListNode curNext=cur.next;
             cur.next=slow;
             slow=cur;
             cur=curNext;
         }
         //判断前后是否相等
         while(head!=slow){
             if(head.val!=slow.val){
                 return false;
             }
             //偶数的情况
             if(head.next==slow){
                 return true;
             }
             head=head.next;
             slow=slow.next;
         }
        return true;
    }
}

代码解析

1:对于寻找中间节点和反转链表的代码我就不再做过多的阐述了,这个可以去看我之前的博客,、
2:这里我主要介绍下对比这里的代码
(1):首先我们先来看奇数链表:拿24->12->78->12->24 这个链表举例
首先寻找链表的中间节点
在这里插入图片描述
寻找过后slow指针和fast指针的位置,此时slow所指向的节点就是我们奇数链表的中间节点,下图中的奇数链表的中间节点为值域为78的这个节点.
在这里插入图片描述
寻找完成后开始定义新变量cur,curNext,开始反转链表,下面是反转链表完成后各个指针的位置:此时cur=curNext=null,slow和fast指针同时指向尾节点.
在这里插入图片描述
反转完成后,此时开始进行判断值域,head指针和slow指针开始向中间节点的位置遍历,在这两个指针还没有到中间节点前进行值域的判断只要有一次两个指针所指向的节点的值域不相同,那么就返回false,否则返回true.

(2):对于偶数链表,我们就拿24->12->12->24这个链表来举例:
我们在奇数链表的基础上加上了对于head.next==slow的判断,先来看为什么要加这个吧:
首先寻找链表的中间节点
在这里插入图片描述
寻找过后slow指针和fast指针的位置,此时slow所指向的节点就是我们偶数链表的中间节点,下图中的偶数链表的中间节点为第二个值域为12的这个节点.
在这里插入图片描述
寻找完成后开始定义新变量cur,curNext,开始反转链表,下面是反转链表完成后各个指针的位置:此时fast=cur=curNext=null,slow指向尾节点.
在这里插入图片描述
反转完成后,此时开始进行判断值域,head指针和slow指针开始向中间节点的位置遍历
在这里插入图片描述

当slow指针遍历到中间节点后,我们会发现此时当slow不能再往下了,原因是slow.next此时存储的地址是slow最开始所在的尾节点,head此时指向第二个节点,如果执行了slow=slow.next语句,相当于slow又回到了尾节点,这个时候的head也来到了中间节点处:如下所示:
在这里插入图片描述
此时继续执行if判断语句,head.val=12,slow.val=24,这两个不相等直接return false,相当于此时程序判断我们的偶数链表24->12->12->24不是一个回文链表,很显眼程序判断错误
所以当head.next=slow的时候,就说明我们偶数链表已经是一个回文链表了
return true即可.

总结

这道题目是很多道题目思路的综合版本,运用到了快慢指针和反转列表中的思路,并加以修饰便可以将这道题目快速解答了,但是仍需要注意细节点,例如奇偶数链表的判断.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值