【leedcode】19. 删除链表的倒数第 N 个结点

378 阅读2分钟

这是我参与8月更文挑战的第13天,活动详情查看:8月更文挑战

难度:中等

题目描述

给你一个链表,删除链表的倒数第 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

解析题目:

方法一: 常规思路:

循环迭代 -- 找到 length -n 个节点

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        dummy = ListNode(0)
        dummy.next = head 

        #首先: 获取链表长度
        cur, length = head, 0 
        while cur:
            length += 1
            cur = cur.next 
        
        #其次: 找到倒数第N个节点的前面一个节点
        cur = dummy
        for _ in range(length - n):
            cur = cur.next
        
        #最后: 删除节点,并重新连接
        cur.next = cur.next.next
        return dummy.next 
 

方法二:快慢指针

-- 找倒数第N个节点的前一个节点

  • 常规套路公式:
  • 链表可以创建快慢两个指针。
  • 右指针先跑n+1,然后左指针在和右指针开始同步向前。当右指针到达末尾时:
  • slow.next = slow.next.next即可!
  • 需要排除下当右指针跑了N+1后,已经超出链表,那么代表链表长度与N相等。
  • 那倒数第N个数就是链表头,此时只需要返回dummy.next即可。
class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        dummy = ListNode(0)
        dummy.next = head 
        
        #首先: 快指针先走n步
        slow, fast = dummy, dummy
        for _ in range(n):
            fast = fast.next 

        #其次: 快慢指针同时走,直到fast指针到达尾部节点,此时slow到达倒数第N个节点的前一个节点
        while fast and fast.next:
            slow, fast = slow.next, fast.next 
        
        #最后: 删除节点,并重新连接
        slow.next = slow.next.next 
        return dummy.next 

方法三:递归迭代

最笨的方法,也是最有效的方法: -- 回溯时,进行节点计数

class Solution:  
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        if not head: 
            self.count = 0
            return head  
        head.next = self.removeNthFromEnd(head.next, n) # 递归调用
        self.count += 1 # 回溯时进行节点计数
        return head.next if self.count == n else head