牛客网:[编程题]回文链表

题目要求:

现给定一个链表ListNode* pHead,定义bool代表链表是否为回文,请编写程序。

测试样例:

{1,2,3,2,1}
返回:true
{1,2,3,2,3}
返回:false

思想:

本题的思路分为三步走:
找寻中间位置->将链表分为两部分,对后一部分进行翻转->进行指针指向数据的比较。
1、找寻中间位置
找寻中间位置,还是运用快慢指针的思想,(具体细节参考我的之前有一篇博客快慢指针的两道题目,里面有详细的讲解)。在对于单链表的操作之中,快慢指针的思想能够帮助我们解决绝大多数部分的问题。
2、将链表分为两部分,对后一部分进行翻转
举个例子:1->2->3->2->1
进行第一步之后,我们得到中间元素对应的val值为3,此时我们定义一个结构体指针变量slow指向此处,此时在定义一个结构体变量为prev,指向slow指向元素的前一个元素,即val值为2的地址。此时找到之后,将prev->next = NULL
即1->2与3->2->1这两个链表。
得到这两个链表之后,对3->2->1进行翻转。
在这里插入图片描述

翻转的思想还是要根据以下的代码去自己手动画图实现一下,加深对这个过程的理解。
翻转完成后,一定要将slow置为reverseHead指向的地址。
3、进行指针指向的val的比较
**特别注意:**循环体进行的条件一定要为原链表pHead指向的元素完后走不为空的情况下进行。
例如,得到1->2与3->2->1这两个链表,pHead指向的地址是1->2中val=1对应的结构体地址,slow指向的地址是3->2->1中val=3对应的结构体地址。此时如果用slow是否为空去判断会造成栈溢出的报错,因此要使用pHead是否为空去判定。

代码实现:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Palindrome {
public:
    bool isPalindrome(ListNode* pHead) {
        // write code here
        if(pHead == NULL)
        {
            return false;
        }
        
        ListNode* fast = pHead;
        ListNode* slow = pHead;
        ListNode* prev = pHead;
        ListNode* reverseHead = NULL;
        
        //1、运用快慢指针找到链表的中间元素
        //若链表元素个数为奇数,则找寻中间元素
        //若链表元素个数为偶数,找出中间元素靠后的那一个元素
        while(fast && fast->next)
        {
            fast = fast->next->next;
            prev = slow;
            slow = slow->next;
        }
        
        //slow指向链表中间元素后,将其前一位链表元素对应的next置为空,变成两个链表
        prev->next = NULL;
        
        //2、从找到的中间位置对其之后的链表元素进行翻转。
        while(slow)
        {
            ListNode* next = slow->next;
            slow->next = reverseHead;
            reverseHead = slow;
            slow = next;
        }
        
        //将翻转之前的slow之前一位的个数置为翻转之后slow指向的位置
        slow = reverseHead;
        
        //3、比较
        while(pHead)
        {
            if(pHead->val != slow->val)
            {
                return false;
            }
            else
            {
                pHead = pHead->next;
                slow = slow->next;
            }
        }
        return true;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值