【力扣算法17】之 19. 删除链表的倒数第 N 个结点 python

简介: 【力扣算法17】之 19. 删除链表的倒数第 N 个结点 python

问题描述

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

示例1

输入:head = [1,2,3,4,5], n = 2

输出:[1,2,3,5]

示例2

输入:head = [1], n = 1

输出:[]

示例3

输入:head = [1,2], n = 1

输出:[1]

提示

  • 链表中结点的数目为 sz
  • 1 <= sz <= 30
  • 0 <= Node.val <= 100
  • 1 <= n <= sz

思路分析

  1. 首先,我们需要删除链表的倒数第n个节点。为了能够找到要删除的节点,我们需要知道链表的长度。
  2. 我们可以通过遍历链表来获取链表的长度。假设链表的长度为length
  3. 然后,我们可以根据链表的长度和要删除的节点的位置,计算出要删除的节点在正向遍历中的位置。假设要删除的节点在正向遍历中的位置为pos
  4. 接下来,我们需要找到要删除的节点的前一个节点,即倒数第n+1个节点。根据第3步计算的位置,我们可以通过遍历链表来定位到该节点。
  5. 最后,将要删除的节点从链表中移除,即将前一个节点的next指针指向下一个节点。

这个思路的关键点是使用双指针的技巧。通过快指针先向前移动n步,可以使得快指针和慢指针之间相差n个节点。然后同时移动快指针和慢指针,直到快指针到达链表的末尾。这样,慢指针所指向的节点就是要删除的节点的前一个节点。

通过这种方法,我们可以在一次遍历中找到要删除的节点的前一个节点,并进行删除操作,而不需要遍历两次链表来实现。


代码分析

  1. 创建一个虚拟头结点 dummy,并将它指向原链表的头结点 head
  2. 定义两个指针 fastslow,初始时都指向虚拟头结点。
  3. 快指针 fast 先向前移动 n 步,即 for i in range(n+1): fast = fast.next
  4. 同时移动快指针和慢指针,直到快指针 fast 到达链表的末尾。使用循环 while fast:,循环内部的操作为 fast = fast.nextslow = slow.next
  5. 此时,慢指针 slow 所指向的节点就是要删除的节点的前一个节点。
  6. 将慢指针 slow 所指向的节点的 next 指针指向下一个节点的 next 指针,即 slow.next = slow.next.next,实现删除倒数第 n 个节点。
  7. 返回 dummy.next,即为新链表的头结点。

完整代码

class Solution(object):
    def removeNthFromEnd(self, head, n):
        dummy = ListNode(0)  # 创建一个虚拟头结点,值为0
        dummy.next = head  # 将虚拟头结点指向原链表的头结点
        fast = dummy  # 快指针初始指向虚拟头结点
        slow = dummy  # 慢指针初始指向虚拟头结点
        for i in range(n+1):  # 快指针先向前移动n步(包括虚拟头结点)
            fast = fast.next
        while fast:  # 同时移动快指针和慢指针,直到快指针到达链表末尾
            fast = fast.next  # 快指针每次移动一步
            slow = slow.next  # 慢指针每次移动一步
        slow.next = slow.next.next  # 删除倒数第n个节点,将慢指针指向的节点的next指针指向下一个节点的next指针
        return dummy.next  # 返回链表的头结点

详细分析


class Solution(object):
• 1

定义一个名为Solution的类。

def removeNthFromEnd(self, head, n):
• 1

定义了一个名为removeNthFromEnd的方法,该方法接受两个参数:head表示链表的头结点,n表示要删除的倒数第n个节点。

dummy = ListNode(0)
• 1

创建一个名为dummy的虚拟头结点,值为0。

dummy.next = head
• 1

将虚拟头结点的next指针指向原链表的头结点,以便建立虚拟头结点与原链表的连接。

fast = dummy
        slow = dummy

初始化快指针fast和慢指针slow,都指向虚拟头结点。

for i in range(n+1):
            fast = fast.next

快指针先向前移动n步(包括虚拟头结点),以建立快慢指针之间的n个节点的距离。

while fast:
            fast = fast.next
            slow = slow.next

同时移动快指针和慢指针,快指针每次向前移动一步,慢指针每次向前移动一步,直到快指针到达链表末尾。

slow.next = slow.next.next
• 1

删除倒数第n个节点,即将慢指针指向的节点的next指针指向下一个节点的next指针。通过跳过要删除的节点实现删除操作。

return dummy.next
• 1

返回链表的头结点,即虚拟头结点的下一个节点,用于处理删除头结点的情况。


运行效果截图


完结

相关文章
|
2月前
|
算法
LeetCode第24题两两交换链表中的节点
这篇文章介绍了LeetCode第24题"两两交换链表中的节点"的解题方法,通过使用虚拟节点和前驱节点技巧,实现了链表中相邻节点的交换。
LeetCode第24题两两交换链表中的节点
|
2月前
|
存储 算法
LeetCode第86题分隔链表
文章介绍了LeetCode第86题"分隔链表"的解法,通过创建两个新链表分别存储小于和大于等于给定值x的节点,然后合并这两个链表来解决问题,提供了一种简单易懂且操作原链表的解决方案。
LeetCode第86题分隔链表
|
2月前
|
存储 算法
LeetCode第83题删除排序链表中的重复元素
文章介绍了LeetCode第83题"删除排序链表中的重复元素"的解法,使用双指针技术在原链表上原地删除重复元素,提供了一种时间和空间效率都较高的解决方案。
LeetCode第83题删除排序链表中的重复元素
|
2月前
|
C++ 索引
leetcode 707.设计链表
本文提供了解决LeetCode 707题"设计链表"的C++实现,包括单链表的节点定义和类方法实现,如添加节点、获取节点值、删除节点等。
|
2月前
|
算法
LeetCode第92题反转链表 II
文章分享了LeetCode第92题"反转链表 II"的解法,通过使用四个指针来记录和更新反转链表段的头部、尾部以及前一个和后一个节点,提供了一种清晰且易于理解的解决方案。
LeetCode第92题反转链表 II
|
2月前
|
存储 算法
【初阶数据结构篇】顺序表和链表算法题
此题可以先找到中间节点,然后把后半部分逆置,最近前后两部分一一比对,如果节点的值全部相同,则即为回文。
20 0
|
3月前
|
机器学习/深度学习 算法 搜索推荐
从理论到实践,Python算法复杂度分析一站式教程,助你轻松驾驭大数据挑战!
【7月更文挑战第22天】在大数据领域,Python算法效率至关重要。本文深入解析时间与空间复杂度,用大O表示法衡量执行时间和存储需求。通过冒泡排序(O(n^2)时间,O(1)空间)与快速排序(平均O(n log n)时间,O(log n)空间)实例,展示Python代码实现与复杂度分析。策略包括算法适配、分治法应用及空间换取时间优化。掌握这些,可提升大数据处理能力,持续学习实践是关键。
68 1
|
4月前
|
存储 机器学习/深度学习 算法
Python算法基础教程
Python算法基础教程
22 0
|
数据采集 SQL 算法
C++、Python、数据结构与算法、计算机基础、数据库教程汇总!
C++、Python、数据结构与算法、计算机基础、数据库教程汇总!
211 0
C++、Python、数据结构与算法、计算机基础、数据库教程汇总!