2026/4/6 22:53:26
网站建设
项目流程
浙江住房和城乡建设厅网站,wordpress历史版本下载地址,企业备案 网站服务内容,wordpress商城实战教程处理链表区间反转的关键在于#xff1a;找到待反转区间的前驱节点#xff0c;并将该区间内的节点逐个“移到”前面。1. 解题思路#xff1a;一次遍历#xff08;穿针引线法#xff09;
为了简化边界条件#xff08;比如从第一个节点就开始反转#xff09;#xff0c;我…处理链表区间反转的关键在于找到待反转区间的前驱节点并将该区间内的节点逐个“移到”前面。1. 解题思路一次遍历穿针引线法为了简化边界条件比如从第一个节点就开始反转我们通常先创建一个虚拟头节点 (Dummy Node)。定位前驱节点移动指针pre到待反转区间的前一个位置第left - 1个节点。设置当前操作指针cur指向区间的第一个节点next指向cur的下一个节点。循环进行头插法执行right - left次操作。每次将next节点插入到pre之后从而实现局部反转。2. 代码实现 (Python)# Definition for singly-linked list.# class ListNode:# def __init__(self, val0, nextNone):# self.val val# self.next nextclassSolution:defreverseBetween(self,head:Optional[ListNode],left:int,right:int)-Optional[ListNode]:# 1. 设置 dummy node 防止 head 被反转的特殊情况dummyListNode(0)dummy.nexthead predummy# 2. 找到 left 的前一个节点for_inrange(left-1):prepre.next# 3. 开始局部反转curpre.nextfor_inrange(right-left):next_nodecur.next# 将 next_node 从链表中摘除插入到 pre 后面cur.nextnext_node.nextnext_node.nextpre.nextpre.nextnext_nodereturndummy.next3. 测试用例与结果测试用例 1输入:head [1, 2, 3, 4, 5],left 2,right 4过程简述:pre指向节点1。第一次循环把3提到1后面。链表变为1 - 3 - 2 - 4 - 5。第二次循环把4提到1后面。链表变为1 - 4 - 3 - 2 - 5。预期输出:[1, 4, 3, 2, 5]测试用例 2输入:head [5],left 1,right 1预期输出:[5]4. 复杂度分析时间复杂度:O(N)O(N)O(N)其中NNN是链表长度。我们只需要遍历一次链表。空间复杂度:O(1)O(1)O(1)我们只使用了常数级别的额外指针空间。在 Python 中for _ in range(n):是一种非常地道的写法主要用于“只需要循环执行特定次数但并不关心当前循环到第几次”的场景。1. 下划线_的含义在 Python 中下划线_是一个约定俗成的占位符。通常for i in range(5):中的i会存储当前循环的索引0, 1, 2…。如果你在循环体内部完全不需要用到这个索引数字使用_可以告诉阅读代码的人“这个变量不重要我只是想让这段代码运行nnn次。”1. 为什么要定义dummy(虚拟头节点)在处理链表问题时dummy节点就像是一个“救生圈”它的主要作用是消除边界条件的特殊处理。如果没有dummy如果left 1意味着你要从原链表的第一个节点开始反转。此时反转后的“新头节点”会发生变化。你需要写额外的if...else逻辑来处理“头节点被改变”的情况。有了dummy我们将dummy.next指向head。无论你反转的是中间一段还是从第一个节点开始反转head节点都变成了“中间某个节点”。最终结果只需返回dummy.next它永远指向反转后正确的起始位置逻辑变得整洁统一。2. 为什么用循环去找链表 vs 数组这正是由链表的物理结构决定的数组 (Python 的 List)特性连续内存存储。查找支持“随机访问”。你可以直接通过下标arr[i]在O(1)O(1)O(1)时间内找到任何元素就像查字典的页码一样快。缺点插入或删除中间元素时需要挪动后面的所有元素非常费力。链表 (Linked List)特性分散内存存储节点之间靠指针地址连接。查找不支持随机访问。你想找第nnn个节点必须从第一个节点开始顺着next指针一个一个数过去即你看到的for循环。这就是O(N)O(N)O(N)的查找时间。优点只要你找到了位置插入和删除操作只需要改变指针指向不需要移动数据非常高效。3. “定位到前一个”的必要性在链表中如果你想删除或移动节点B你手里必须握着节点AB的前驱节点的指针。因为链表是单向的如果你直接跳到了left位置你无法回过头去修改left-1节点的next指向。所以我们必须“未雨绸缪”让pre停在left的前一个位置这样我们才能把后面反转好的部分重新接回到主链表上。总结对比特性数组 (List)链表 (Linked List)访问第kkk个元素极快O(1)O(1)O(1)较慢O(k)O(k)O(k)必须遍历中间插入/删除较慢O(N)O(N)O(N)极快O(1)O(1)O(1)定位后适用场景频繁查询、尾部增删频繁在中间增删、容量动态变化一句话总结链表就像玩“寻宝游戏”每一关只给你下一关的线索所以你想去哪都得从第一关开始闯而数组就像是有门牌号的公寓你可以直接瞬移到任何一间房。