• Python编程题48删除链表的倒数第 N 个结点


    题目

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

    例如:

    原链表转换为列表:[1, 2, 3, 4, 5],需要删除倒数第2个节点
    最终的链表转换为列表:[1, 2, 3, 5]

    原链表转换为列表:[1],需要删除倒数第1个节点
    最终的链表转换为列表:[]

    原链表转换为列表:[1, 2],需要删除倒数第1个节点
    最终的链表转换为列表:[1]

    已知 链表节点的定义、链表与列表相互转换 的代码如下:

    class ListNode:  # 单链表
        def __init__(self, val=0, next=None):
            self.val = val  # 链表节点上存储的元素
            self.next = next  # 指向下一个链表节点
    
    
    def list_to_list_node(numbers):  # 将列表转换为单向链表,并返回链表的头节点
        dummy_head = ListNode(0)
        pre = dummy_head
        for number in numbers:
            pre.next = ListNode(number)
            pre = pre.next
        pre = dummy_head.next
        return pre
    
    
    def list_node_to_list(node):  # 将单向链表转换为列表
        result = []
        while node:
            result.append(node.val)
            node = node.next
        return result
    

    实现思路1

    • 要删除链表的倒数第 n 个节点,我们可以先计算出链表长度length,然后再进行处理,假设求出链表长度length为5
    • 如果要删除链表的倒数第 2 个节点,也就是第4个节点,此时我们只需要让链表的第 3 个节点,通过 next 指向到第 5 个节点即可
    • 有一种情况,如果要删除的节点恰好是链表的头节点,这个情况在原链表上就不好处理,因为前面没有头节点了,所以,我们统一设置一个虚拟头节点 dummy_head 进行处理,而 dummy_head 通过 next 指向原链表的头节点就行

    代码实现1

    class Solution:
        def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
            dummy_head = ListNode(next=head)  # 设置一个虚拟头节点
            cur1, length = dummy_head, 0
            while cur1 is not None:  # 计算链表的长度
                length += 1
                cur1 = cur1.next
            cur2, step = dummy_head, length - 1 - n  # step 表示被删除节点的前一个位置,减去1是因为多了一个虚拟头节点
            while step:
                cur2 = cur2.next
                step -= 1
            cur2.next = cur2.next.next  # 跳过下一个节点,直接指向下下个节点
            return dummy_head.next
    
    • 时间复杂度:O(n)
    • 空间复杂度:O(1)

    实现思路2

    • 使用 双指针 的方式来实现
    • 设置两个节点指针:slow、fast,fast先移动 n 位,然后再让slow、fast同时移动,直到fast指向的下一个节点为空时,二者均停止移动
    • 此时,slow 指向的是链表中要删除节点的前一个节点,我们只需要让当前节点通过 next 指向下下个节点即可

    代码实现2

    class Solution:
        def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
            dummy_head = ListNode(next=head)  # 设置一个虚拟头节点
            slow, fast = dummy_head, dummy_head  # 设置两个节点指针
            while n:  # fast先移动 n 步
                fast = fast.next
                n -= 1
            while fast.next is not None:  # slow和fast同时移动,当fast指向空节点退出循环
                fast = fast.next
                slow = slow.next
            slow.next = slow.next.next  # slow指向下下个节点(相当于跳过下一个节点,也就是倒数第N个节点)
            return dummy_head.next
    
    • 时间复杂度:O(n)
    • 空间复杂度:O(1)

    实现思路3

    • 使用 的方式实现,但空间复杂度会变为 O(n)
    • 定义一个栈 stack,遍历链表,让所有节点入栈
    • 要删除链表的倒数第 n 个节点,只需让 stack 执行 n 次出栈操作,此时栈顶就恰好为待删除节点的前一个节点
    • 接着让栈顶节点通过 next 指向下下个节点即可

    代码实现3

    class Solution:
        def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
            dummy_head = ListNode(next=head)  # 设置一个虚拟头节点
            cur, stack = dummy_head, []
            while cur is not None:  # 所有节点入栈
                stack.append(cur)
                cur = cur.next
            while n:  # 执行 n 次出栈操作
                stack.pop()
                n -= 1
            cur = stack[-1]  # 获取栈顶元素,此时栈顶恰好为待删除节点的前一个节点
            cur.next = cur.next.next  # 跳过下一个节点,直接指向下下个节点
            return dummy_head.next
    
    • 时间复杂度:O(n)
    • 空间复杂度:O(n)

    更多Python编程题,等你来挑战:Python编程题汇总(持续更新中……)

  • 相关阅读:
    Implementation of Message Receiver
    Data Model for Message Receiver
    SQL SERVER 批量生成编号
    修改hosts文件
    PHP-问题处理验证码无法显示出来
    PHP-问题处理Fatal error: Uncaught Error: Call to undefined function mb_strlen()
    PHP-问题处理Fatal error: Uncaught Error: Call to undefined function simplexml_load_file()
    10进制转33进制
    PHP-生成缩略图和添加水印图-学习笔记
    SQLServer地址搜索性能优化例子
  • 原文地址:https://www.cnblogs.com/wintest/p/15854969.html
Copyright © 2020-2023  润新知