LeetCode 234. 回文链表(C++)

题目地址:力扣

解法1:将链表复制到数组里再从两头比对

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        vector<int> listvec;
        // 把链表中元素都插入数组
        while (head!= nullptr)
        {
            listvec.push_back(head->val);
            head = head->next;
        }

        // 一个迭代器从头,一个迭代器从尾
        auto it_head = listvec.begin();
        auto it_back = listvec.end() - 1;
        // 若迭代器相遇了则说明都检查完了,可以返回true
        while (it_back - it_head > 0)
        {    
            // 检查到值不相等就返回false
            if ((*it_head++) != (*it_back--))
                return false;                    
        }
        return true;
    }
};

解法2:递归法

解法1的问题在于要开辟额外数组,递归虽然不用开辟额外空间,但是需要占用系统栈的空间,而且效率可能还更差。

这种方法需要一个额外的节点用来保存链表头结点,并且在递归到达最里层的时候往后走,这样就可以实现头指针向后,尾指针向前对比。

class Solution {
public:
    // 递归函数
    bool check(ListNode* curNode)
    {
        // 若当前节点不为空
        if (curNode != nullptr)
        {
            // 因为是从下往上的,判断检查更里面的递归是否是false,是的话直接返回false
            if (!check(curNode->next))
                return false;    
            // 更里面是true就检查当前层的情况
            if (curNode->val != headnode->val)
                return false;
            // 当前层也满足的话就把headnode往后
            headnode = headnode->next;
        }
        // 当前节点为空,或者经历了上面的检查以后返回true
        return true;
    }


    bool isPalindrome(ListNode* head) {
        headnode = head;
        return check(head);
    }
    ListNode* headnode;
};

解法3:快慢指针法

思路:要判断回文链表,可以把链表的后面部分反转,然后再对比就行了。而要找到链表中部,就需要采用快慢指针的方法,快指针一次走两步,慢指针一次走一步,如果快指针的next不为空就走一步,如果next->next不为空就再走一步,同时走第二步的时候慢指针也走一步。这样慢指针指到中间的时候,快指针正好指到表尾。然后从慢指针的next开始反转,反转之后依次判断是否相等,值得注意的是因为mid指向反转后的链表并没有断开,因此判断的结束条件是快指针的next为空。同时要注意只有一个节点的情况,因此反转链表的时候要判断一下head是否为空。

class Solution {
public:
    // 反转链表函数
    void reverse(ListNode *head)
    {
        if (head != nullptr)
        {
            ListNode *prevNode = nullptr;
            ListNode *currNode = head;
            ListNode *nextNode = head;
            
            while(nextNode != nullptr)
            {
                nextNode = currNode->next;
                currNode->next = prevNode;
                prevNode = currNode;
                currNode = nextNode;
            }
        }
    }

    bool isPalindrome(ListNode* head) {
        ListNode *mid = head, *tail = head;
        // mid找到中间的节点,tail找到尾部节点
        while (tail->next != nullptr)
        {
            tail = tail->next;
            if (tail->next != nullptr)
            {
                tail = tail->next;
                mid = mid->next;
            } else
                break;
        }
        // 反转mid后面的链表
        reverse(mid->next);
        // 开始判断是否回文
        while(tail != nullptr)
        {
            if (head->val != tail->val)
                return false;
            else
            {
                head = head->next;
                tail = tail->next;
            }
        }
        return true;
    }
};

Accepted

  • 88/88 cases passed (160 ms)
  • Your runtime beats 90.08 % of cpp submissions
  • Your memory usage beats 85.66 % of cpp submissions (111.3 MB)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值