leetcode hot100 之 回文链表

该博客介绍了如何判断一个链表是否是回文结构,提供了两种思路。思路一利用栈实现,时间复杂度和空间复杂度均为O(n);思路二通过反转链表的后半部分,空间复杂度优化为O(1),然后对比两部分节点值。代码展示了具体的实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

给定一个链表,请判断其是否是回文链表。
在这里插入图片描述

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

原题链接:https://leetcode.cn/problems/palindrome-linked-list/

思路

思路1

首先计算链表的长度,这样便于把链表分为两半。
一个不用改变原链表的方式,就是借用栈,将前半部分入栈。再遍历后半部分,同时不断出栈和相应的节点对比即可。这种方法好处是不用改变原链表,但是会有额外空间开销。

这里可以更极致一点优化,其实找中间节点时,可以通过快慢指针来实现。而不是先遍历一遍计算长度。

  • 复杂度分析
    • 时间复杂度 O(n)。
    • 空间复杂度 O(n)。
思路2

如果不想有额外的空间开销,则需要改变原链表,如将后半部分进行反转,再将前后两部分逐一比较。

  • 复杂度分析
    • 时间复杂度 O(n)。
    • 空间复杂度 O(1)。

代码

代码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) {
        int n = 0;
        ListNode* temp = head;
        while(temp) {
            n++;
            temp = temp->next;
        }
        int m = n / 2;
        ListNode* cur = head;
        stack<ListNode*> node_stack;
        while(m > 0) {
            m--;
            node_stack.push(cur);
            cur = cur->next;
        }
        // 长度为奇数时,跳过最中间的节点
        if (n % 2 == 1) {
            cur = cur->next;
        }
        while (cur) {
            ListNode* prev = node_stack.top();
            if (cur->val != prev->val) {
                return false;
            }
            node_stack.pop();
            cur = cur->next;
        }
        return true;
    }
};
代码2
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if (head == NULL || head->next == NULL) {
            return true;
        }
        int n = 0;
        ListNode* temp = head;
        while(temp) {
            temp = temp->next;
            n++;
        }
        temp = head;
        int m = n / 2;
        while (m > 0) {
            temp = temp->next;
            m--;
        }
        if (n % 2 == 1) {
            temp = temp->next;
        }   
        ListNode* prev = temp;
        ListNode* cur = temp->next;
        prev->next = NULL; //必须加这句,不知道为啥,否则cur->next 不能指向 prev,不能形成回环
        while (cur) {
            ListNode* next = cur->next;
            cur->next = prev;
            prev = cur;
            cur = next;
        }
        m = n / 2;
        while (m > 0) {
            if (prev->val != head->val) {
                return false;
            }
            head = head->next;
            prev = prev->next;
            m--;
        }
        return true;
    }
};
### LeetCode Hot100 刷题技巧与策略 LeetCodeHot100 是许多程序员提升算法能力的重要资源之一。以下是针对该部分刷题的一些技巧和策略: #### 1. **制定合理的刷题计划** - 推荐按照一定的顺序进行刷题,例如优先完成热题 HOT 100 和精选 TOP 面试题[^1]。这些题目覆盖了大部分常见的算法知识点和技术面试考点。 - 将题目按难度分类(简单、中等、困难),逐步攻克不同层次的挑战。 #### 2. **利用辅助工具提高效率** - 借助公子龙大佬开发的刷题网站及其插件功能[^2],可以更高效地查找解题思路并学习经典算法框架。 - 插件能够帮助用户快速定位到某类问题的核心解决方法,减少无谓的时间浪费。 #### 3. **注重总结归纳** - 对于每一道做过的题目,都应该尝试分析其背后的通用模式以及可能的变化形式[^4]。比如环形链表的相关变种问题(如回文链表)往往具有相似逻辑结构。 - 定期整理笔记,记录下自己容易遗忘的知识点或者巧妙的解决方案。 #### 4. **模拟真实场景训练** - 如果目标是为了准备技术面试,则建议模仿实际考试环境来进行限时答题练习[^5]。这样不仅可以锻炼思维敏捷度还能增强抗压能力。 - 同时也要关注时间复杂度空间复杂度优化等方面的要求。 #### 5. **积极参与社区讨论** - 加入像寸铁这样的优质创作者所创建的学习小组或论坛,与其他志同道合者共同探讨难题解答方案。 - 学习他人优秀的思维方式有助于拓宽视野开阔眼界。 下面提供一段简单的 Python 实现代码作为例子展示如何处理其中一类常见数据结构——链表的操作: ```python class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def hasCycle(head: ListNode) -> bool: slow = fast = head while fast and fast.next: slow = slow.next # Move one step at a time. fast = fast.next.next # Move two steps at once. if slow == fast: # If there's an intersection point found. return True return False # No cycle detected after traversal completes. ``` 此函数用于检测单向链表是否存在闭环现象,采用双指针法实现。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值