练题100天——DAY44:回文链表 ★★☆☆☆

今天是休息日,所以有时间练一道题。

最近也在学习数据库,之后会更新一个图书管理系统的完整实现。

题目

234. 回文链表 给你一个单链表的头节点 head ,请你判断该链表是否为回文链表(回文序列是向前和向后读都相同的序列)。如果是,返回 true ;否则,返回 false

我的思路

将链表每个结点的val值存放到一个数组中,然后对数组检测其是否"回文"。

这道题最开始想到的是:用两个指针指向链表的头和尾,然后比较链表的头尾值,然后向中间移动指针,不相等返回false,两个指针相遇的过程一直都相等,则返回true,但是题目的链表为单向的,无法直接获取一个结点的前驱结点,所以我想到了将链表各结点的值存放的数组中,利用这个办法实现比较。

创建数组,需要知道长度,所以需要先遍历一次链表,获取结点数作为数组的长度。

然后再次遍历链表,将各结点的值存入到数组中

最后"遍历"数组,判断是否回文

代码
cpp 复制代码
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if (head->next == NULL) {
            return true;
        }
        ListNode* p = head;
        int len = 0;
        while (p != NULL) {
            len++;
            p = p->next;
        }
        vector<int> arr(len);
        p = head;
        for (int i = 0; i < len && p != NULL; i++) {
            arr[i] = p->val;
            p = p->next;
        }
        int left = 0, right = len - 1;
        while (left < right) {
            if (arr[left] != arr[right]) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
};

复杂度

n为链表的结点数

时间复杂度:O(n)。三次遍历,第一、二次都是遍历整个链表,时间复杂度为O(n),第三次算是遍历半个链表O(n/2),所以总的时间复杂度为O(n)+O(n)+O(n/2)=O(n)。

空间复杂度:O(n)。数组申请的空间为n。

官方题解

方法一:快慢指针

要想让空间复杂度为O(1),就需要对链表自身做处理,将链表分为前后两部分,因为无法直接获取结点的前驱,所以可以将后半部分链表反转,这样就可以直接比较两部分各个结点的值,比较完成后,将后半部分链表再反转回来即可,因为使用该函数的人并不希望链表结构被改变。

但是该方法也有缺点:在并发环境下,函数运行时需要锁定其他线程或进程对链表的访问,因为在函数执行过程中链表会被修改。

根据以上说明,算法流程可分为以下几步:

1.找到前半部分链表的尾结点

2.反转后半部分链表:

可以直接使用练题100天------DAY43:统计前后缀下标Ⅰ+反转链表-CSDN博客的函数

3.比较结点值,判断是否回文

4.恢复链表

5.返回结果

代码
cpp 复制代码
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if (head == nullptr) {
            return true;
        }

        // 找到前半部分链表的尾节点并反转后半部分链表
        ListNode* firstHalfEnd = endOfFirstHalf(head);
        ListNode* secondHalfStart = reverseList(firstHalfEnd->next);

        // 判断是否回文
        ListNode* p1 = head;
        ListNode* p2 = secondHalfStart;
        bool result = true;
        while (result && p2 != nullptr) {
            if (p1->val != p2->val) {
                result = false;
            }
            p1 = p1->next;
            p2 = p2->next;
        }

        // 还原链表并返回结果
        firstHalfEnd->next = reverseList(secondHalfStart);
        return result;
    }

    ListNode* reverseList(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* curr = head;
        while (curr != nullptr) {
            ListNode* nextTemp = curr->next;
            curr->next = prev;
            prev = curr;
            curr = nextTemp;
        }
        return prev;
    }

    ListNode* endOfFirstHalf(ListNode* head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while (fast->next != nullptr && fast->next->next != nullptr) {
            fast = fast->next->next;
            slow = slow->next;
        }
        return slow;
    }
};

复杂度

n 指的是链表的大小

时间复杂度:O(n)。

空间复杂度:O(1)。只会修改原本链表中节点的指向,而在堆栈上的堆栈帧不超过 O(1)。

方法二:递归

这种方法相较于前面两种方法,更难理解。

这里也只给出代码,感兴趣的可以去官方题解看。

代码
cpp 复制代码
class Solution {
    ListNode* frontPointer;
public:
    bool recursivelyCheck(ListNode* currentNode) {
        if (currentNode != nullptr) {
            if (!recursivelyCheck(currentNode->next)) {
                return false;
            }
            if (currentNode->val != frontPointer->val) {
                return false;
            }
            frontPointer = frontPointer->next;
        }
        return true;
    }

    bool isPalindrome(ListNode* head) {
        frontPointer = head;
        return recursivelyCheck(head);
    }
};
相关推荐
LuminousCPP1 小时前
数据结构 - 线性表第四篇:C 语言通讯录优化升级全记录(踩坑 + 思考)
c语言·开发语言·数据结构·经验分享·笔记·学习
AI算法沐枫2 小时前
深度学习python代码处理科研测序数据
数据结构·人工智能·python·深度学习·决策树·机器学习·线性回归
m0_629494733 小时前
LeetCode 热题 100-----26.环形链表 II
数据结构·算法·leetcode·链表
壹号用户4 小时前
用队列实现栈
数据结构·算法
欧米欧5 小时前
C++进阶数据结构之搜索二叉树
开发语言·数据结构·c++
小江的记录本5 小时前
【Java基础】反射与注解:核心原理、自定义注解、注解解析方式(附《思维导图》+《面试高频考点清单》)
java·数据结构·python·mysql·spring·面试·maven
Trouvaille ~6 小时前
【Redis篇】初识 Redis:特性、应用场景与版本演进
数据结构·数据库·redis·分布式·缓存·中间件·持久化
向日的葵0068 小时前
从IO视角深度对比:BST、红黑树、B树、B+树
数据结构·b树
小羊在睡觉8 小时前
力扣239. 滑动窗口最大值
数据结构·后端·算法·leetcode·go
我星期八休息9 小时前
Linux系统编程—库制作与原理
linux·运维·服务器·数据结构·人工智能·python·散列表