练题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);
    }
};
相关推荐
罗湖老棍子1 天前
【例 2】数星星 Stars(信息学奥赛一本通- P1536)
数据结构·算法·树状数组·单点修改 区间查询
重生之后端学习1 天前
62. 不同路径
开发语言·数据结构·算法·leetcode·职场和发展·深度优先
重生之后端学习1 天前
64. 最小路径和
数据结构·算法·leetcode·排序算法·深度优先·图论
样例过了就是过了1 天前
LeetCode热题100 路径总和 III
数据结构·c++·算法·leetcode·链表
再难也得平1 天前
力扣41. 缺失的第一个正数(Java解法)
数据结构·算法·leetcode
实心儿儿1 天前
算法2:链表的中间结点
数据结构·算法·链表
玛卡巴卡ldf1 天前
【LeetCode 手撕算法】(双指针) 1-两数之和、283-移动零、11-盛最多水的容器、15-三数之和
数据结构·算法·leetcode
不想看见4041 天前
Single Number位运算基础问题--力扣101算法题解笔记
数据结构·算法
李昊哲小课1 天前
Python 高级数据结构
开发语言·数据结构·python
我头发还没掉光~1 天前
【C++写详细总结①】从for循环到算法初步
数据结构·c++·算法