回文链表

    回文链表其实也是链表反转的变形;也可以用栈实现。

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

#include <stdio.h>
#include <iostream>
using namespace  std;

struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(nullptr) {}
};


//思路1:空间O(n) 整个链表遍历两边, 开一个栈,第一遍遍历把链表中每个元素push进栈中,这样堆中的元素的pop顺序就是链表的倒序输出;第二遍就开始pop栈中数据,每pop一个数据,就把这个数据跟链表中进行对比,如果相同继续往下走,如果不同返回false。
//
//思路2:空间O(1),使用快慢指针法,第一步设置一个块指针和一个慢指针,快指针一次走两步,慢指针一次走一步(慢),当快指针下一步为null的时候说明慢指针已经走了一半,这就可以找到中间节点。第二步反转中间链表后面的指针,第三部从头尾向中间扫描,对比每个元素是否相等,如果都相等,则是回文数,否则不是回文数。(下面网友易水给出了代码实现,这里不再叙述)

class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        // write code here
    
        ListNode* pSlow = A;
        ListNode* pQucik = A;
        //快慢指针找到中间节点
        while (pQucik!=nullptr&&pQucik->next!=nullptr)
        {
            pQucik = pQucik->next->next;
            pSlow = pSlow->next;
            
        }
        //将中点结点后的指针反转
        ListNode* pNode = nullptr;
        pNode = pSlow->next;
        ListNode* pHead = pSlow;  //反转链表的头
        while (pNode!=nullptr)   //测试未通过
        {
            ListNode* temp = pNode;
            pNode = pNode->next;
            temp->next = pHead;
            pHead = temp;
        }
        while (A!=pHead)
        {
            if (A->val!=pHead->val)
            {
                return false;
            }
            A = A->next;
            pHead = pHead->next;
        }
        return true;
    }
};

class PalindromeList1 {
public:
    bool chkPalindrome(ListNode* A) {  //A不带头节点
        // write code here
        if (A == nullptr || A->next == nullptr)
            return true;
        ListNode* head = nullptr;
        ListNode* node = A;

    /*    //将中间节点后的指针反转        
        ListNode* p = slow->next;
        ListNode* p1 = p->next;
        while (p != NULL){
            p->next = slow;
            slow = p;
            p = p1;
            p1 = p1->next;
        }*/

        while (node != nullptr){
            ListNode* temp = node;
            node = node->next;
            temp->next = head;
            head = temp;
        }
        while (A != nullptr&&head != nullptr){
            if (A->val != head->val){
                return false;
            }
            A = A->next;
            head = head->next;
        }
        return true;
    }
};

void print(ListNode* pHead)
{
    if (pHead==nullptr)
    {
        puts("链表为空!");
        return;
    }
    puts("链表为:");
    ListNode*pNode = pHead->next;
    while (pNode)
    {
        printf("%d ->", pNode->val);
        pNode = pNode->next;
    }
    cout << "NULL\n";
}

ListNode* create()
{
    ListNode* pHead, *pNode, *temp;
    int x;
    pHead = pNode = (ListNode*)malloc(sizeof(ListNode));  //带头节点的链表
    printf("请输入链表数据,以0为结束标志:\n");
    scanf("%d", &x);
    while (x)
    {
        temp = (ListNode*)malloc(sizeof(ListNode));
        temp->val = x;
        pNode->next = temp;
        pNode = temp;
        scanf("%d", &x);
    }
    pNode->next = nullptr;
    return pHead;
}


int main()
{
    ListNode *pHead = create();
    print(pHead);
    PalindromeList s;
    bool val=s.chkPalindrome(pHead);
    cout << val << endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值