当前位置: 首页 > news >正文

力扣DAY24 | 热100 | 回文链表

前言

简单 √ 是反转链表的衍生题,很快写完了。不过没考虑到恢复链表结构的问题。

题目

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

示例 1:

输入:head = [1,2,2,1]
输出:true

示例 2:

输入:head = [1,2]
输出:false

提示:

  • 链表中节点数目在范围[1, 105] 内
  • 0 <= Node.val <= 9

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

思路

一开始想着把链表直接反转存储,然后同时遍历。但是考虑到题目要求的O(1)空间复杂度,想到可以只把前半部分,从中间开始向两边遍历。如果链表长度为奇数,跳过最中间的那个数。

我的题解

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        
        if (!head || !head->next){
            return true;
        }
        
        //链表长度
        ListNode* node = head;
        int count = 1;
        while (node->next){
            node = node->next;
            count++;
        }

        //反转一半的链表,分奇偶两种情况
        int len = count / 2;
        ListNode* pre = nullptr;
        ListNode* cur = head;
        while (len--){
            ListNode* nextnode = cur->next;
            cur->next = pre;
            pre = cur;
            cur = nextnode;
        }
        ListNode* left = pre;
        ListNode* right = cur;
        if (count % 2 != 0){
            right = right->next;
        }

        //左右同时开始遍历
        while (left && right){
            if (left->val != right->val){
                return false;
            }
            left = left->next;
            right = right->next;
        }

        return true;
    }
};

官方题解

将值复制到数组中后用双指针法

  1. 复制链表值到数组列表中。
  2. 使用双指针法判断是否为回文。
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        vector<int> vals;
        while (head != nullptr) {
            vals.emplace_back(head->val);
            head = head->next;
        }
        for (int i = 0, j = (int)vals.size() - 1; i < j; ++i, --j) {
            if (vals[i] != vals[j]) {
                return false;
            }
        }
        return true;
    }
};

快慢指针

  1. 找到前半部分链表的尾节点。
  2. 反转后半部分链表。
  3. 判断是否回文。
  4. 恢复链表。
  5. 返回结果。

跟笔者思路差不多,不过多了还原链表结构的步骤

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;
    }
};

心得

有了反转链表的基础,思路就很快想到了。一半反转,同时遍历即可。但是笔者没考虑到还原链表结构,这里暴露出笔者缺乏全局思考,代码拓展性的问题,纯粹是为了做题而做题,有点丢了本心,警醒!另外,反转链表还有个缺点就是需要锁定整个链表来解答,对于系统也不友好。最后,这里再加一个用栈的做法,比数组的做法更好,不过不是O(1)空间复杂度。

相关文章:

  • Apollo 相关知识点
  • DeepSeek组网的演进与效率提升
  • Categorical分布(分类分布):深度学习中的离散建模利器
  • 【嵌入式学习2】学生信息管理系统项目
  • 蓝桥刷题note10(最长回文串,种花问题,柠檬水找零)
  • 基于Spring Boot + Vue的银行管理系统设计与实现
  • SQL语句---DDL
  • 机器视觉场景应用中,有没有超景深的工业镜头
  • HRP方法全文总结与模型流程解析
  • 如何理解响应式编程
  • 【C语言】内存函数详解
  • Oracle归档配置及检查
  • OpenGL(一)图形编程的基石
  • 达梦数据库的sql基本语法
  • 清晰易懂的 Node.js 彻底卸载与清理教程
  • Linux内核的页面错误:原因与解决方案
  • IO模型种类
  • 宫庭海:三十载光影铸就文化传奇
  • Python:单例模式魔法方法
  • 为何AI系统比以往任何时候都更需要红队测试
  • 5月12日至13日北京禁飞“低慢小”航空器
  • 《2025城市青年旅行消费报告》发布,解码青年出行特征
  • 联想发布超级智能体矩阵,杨元庆:美国关税影响反映在产品定价上,未来不确定性很大
  • 再有20余篇论文出现“妇科男患者”“前列腺女患者”,如何破除“水论文”灰产链?
  • 汪海涛评《线索与痕迹》丨就虚而近实
  • 央行:5月15日起下调金融机构存款准备金率0.5个百分点