小鑫的算法之路:leetcode0234 回文链表

题目

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false

进阶:你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

解法1

如果要比较是否为回文链表,可将链表中的数据保存至一个vector容器中,然后将链表由头到尾,vector容器由尾到头,逐一对值进行比较。如果值完全一致,则为回文链表,否则不为回文链表。

代码如下:

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        vector<int> buffer{};
        ListNode* tmp = head;
        while (tmp != nullptr) {
            buffer.push_back(tmp->val);
            tmp = tmp->next;
        }
        
        int size = buffer.size();
        for (int i = size - 1; i >= size / 2; --i) {
            if (buffer[i] != head->val) {
                return false;
            }
            head = head->next;
        }

        return true;
    }
};

时间复杂度为O(n),空间复杂度为O(n)。执行结果如下:

在这里插入图片描述

解法2:递归法

可以通过递归遍历至节点的尾部,这样出栈的时候就可以逆序访问链表节点了。在类的内部保存一个节点存储链表的头指针,而递归遍历至节点尾部后就可以逆序遍历链表节点。如果两个值一致,将继续递归出栈,而当前的节点往后移动。如果两个值不一致,则不进行比较,直接返回false,表示为非回文链表。

代码如下:

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        curHead_ = head;
        return check(head);
    }

private:
    bool check(ListNode* node) {
        if (node == nullptr) {
            return true;
        }

        // 前一次比较结果为true,才进行本次比较处理,否则直接返回false
        if (!check(node->next)) { 
            return false;
        }

        // 前后两个节点的值不一致,直接返回false
        if (node->val != curHead_->val) {
            return false;
        }

        curHead_ = curHead_->next;

        return true;
    }

private:
    ListNode* curHead_{nullptr};
};

时间复杂度为O(n),空间复杂度为O(1)。执行结果如下:

在这里插入图片描述

解法3:快慢指针

分别定义一个快指针和慢指针,快指针每次走两步,慢指针每次走一步,这样快指针遍历到尾部后,慢指针到链表的中间节点,并且慢指针在前进的过程反转链表,这样就可以从中间向两边开始遍历,从而判断链表是否为回文链表。

代码如下:

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        ListNode* slow = head;
        ListNode* fast = head;
        // 找到链表中点
        while ((fast != nullptr) && (fast->next != nullptr)) {
            fast = fast->next->next;
            slow = slow->next;
        }

        // 反转链表前半部分
        ListNode* pre = nullptr;
        ListNode* cur = head;
        while (cur != slow) {
            ListNode* next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }

        // 前半部分链表逆序后的头节点
        ListNode* left = pre;
        // 后半部分链表的头节点,和链表的节点个数的奇偶有关系
        ListNode* right = (fast == nullptr) ? slow : slow->next;
        while ((left != nullptr) && (right != nullptr)) {
            if (left->val != right->val) {
                return false;
            }
            left = left->next;
            right = right->next;
        }

        return true;
    }
};

时间复杂度为O(n),空间复杂度为O(1)。执行结果如下:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值