牛客题霸面试真题——链表:NC96 判断一个链表是否为回文结构


在这里插入图片描述

解法一:对后半段进行翻转,再逐个比较

如果此题是判断一个字符串是否为回文结构的话,那么很容易想到:用两个指针,左边的指向头部,右边的只指向尾部,两边同时向中间移动逐字匹配,如果发现有一个没有匹配上那么此串边不是回文结构。

此题使用的是链表,只能从头向尾的方向进行移动,所以不能直接按照上述方法进行匹配。如果想按上述步骤进行,需要将中间到后面的节点间的next反向,这样才能从尾部向中间进行移动。(注:如果该链表是回文结构,那么一定是对称的,所以可以将中间到后面的next指针反向)

在这里插入图片描述

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */

class Solution {
public:
    /**
     * 
     * @param head ListNode类 the head
     * @return bool布尔型
     */
    ListNode* Reverse(ListNode *head){
        ListNode *pre=nullptr;
        ListNode *cur=head;
        ListNode *nex=nullptr;
        while(cur){
            nex=cur->next;
            cur->next=pre;
            pre=cur;
            cur=nex;
        }
        return pre;
    }
    bool isPail(ListNode* head) {
        // write code here
        ListNode *slow=head,*fast=head;
        //找中点
        while(fast&&fast->next){
            slow=slow->next;
            fast=fast->next->next;
        }
        //fast不为空说明L为奇数,slow应该后移
        if(fast) slow=slow->next;
        //反转
        slow=Reverse(slow);
        fast = head;
        while(slow){
            if(fast->val!=slow->val) return false;
            fast = fast->next;
            slow = slow->next;
        }
        return true;
        
    }
};

这里标注下该过程出现的bug:
把pre和cur的赋值顺序写错了,应该先将pre赋为cur再修改cur,否则就会导致下图中的pre和cur指向同一节点的情况
在这里插入图片描述
正确代码如下:

    ListNode *Reverse(ListNode *head){
        ListNode *pre=nullptr;
        ListNode *cur=head;
        ListNode *nex=nullptr;
        while(cur){
            nex=cur->next;
            cur->next=pre;
            pre=cur;
            cur=nex;
        }
        return pre;
    }

解法二:使用栈从后向前遍历

我们知道栈的特点是先进后出,所以将链表中的元素放入栈再取出来就可以实现从后到前的遍历了。对于此题,我们只需要将前半段放入栈中,再逐个将栈顶元素与链表后半段进行比较即可。补充栈的初始化等相关操作,转自链接https://www.cnblogs.com/skywang12345/p/3562239.html

具体实现与上题差不多,用slow和fast找中点(slow每次移动一步,fast每次移动两步,图示如下)

  • 若L为奇数,fast->next==nullptr时 slow为中点
  • 若L为偶数,fast=nullptr时 slow为中点偏右

若L为奇数,由于slow指向中点与会问的判断无关,所以不应将此节点入栈,在跳过该节点后,slow指向后半段的第一个节点。此时fast重新指向head(即前半段的第一个节点),逐个比较栈顶与链表前半段的节点,比较后记得将栈顶元素出栈,fast后移。

在这里插入图片描述

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 * };
 */

class Solution {
public:
    /**
     * 
     * @param head ListNode类 the head
     * @return bool布尔型
     */

    bool isPail(ListNode* head) {
        // write code here
        ListNode *slow = head, *fast = head;
        stack<int> s;
        //若L为奇数,fast->next==nullptr时 slow为中点
        //若L为偶数,fast=nullptr时 slow为中点偏右
        while(fast&&fast->next){
            s.push(slow->val);
            fast=fast->next->next;
            slow=slow->next;
        }
        //当L为奇数时slow=slow->next,跳过中点比较后半段
        if(fast) slow=slow->next;
        while(slow){
            if(slow->val!=s.top()) return false;
            slow=slow->next;
            s.pop();
        }
        return true;
    }
};

时间比较

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值