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

示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.

当删除了倒数第二个节点后,链表变为 1->2->3->5. 说明:

给定的 n 保证是有效的。

进阶:

你能尝试使用一趟扫描实现吗?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

1、基本思路

  由于本人自己实现了一个链表类。因此,读者首先需要去 第一篇博客复制链表父类代码(否则代码太长了)。首先统计链表长度,然后正向删除第 length-n 个节点即可。

代码
# -*- coding: utf-8 -*-
# ======================================================
# @Time    : 2021/01/11
# @Author  : lele wu
# @Email   : 2541612007@qq.com
# @File    : delete_n_node.py
# @Comment: 删除链表中倒数第n个节点
# ======================================================

'''
题目描述:
    给定一个链表,删除链表中倒数第n个节点,并且返回头结点.
基本思路:
    首先统计链表长度,然后-n看看删除的是正向的那个节点。这样就容易了。
'''
from lianbiao import lianbiao

class DeleteNNode(lianbiao):
    def __init__(self):
        super(DeleteNNode, self).__init__()
    def delete_n_node(self,n):
        # 统计链表的长度
        pointer = self.head             # 由于需要返回头结点,因此需要保存
        length = 0
        while pointer:
            pointer = pointer.getNext()
            length+=1
        # 初始化
        pointer = self.head
        # 找出正向需要删除的节点
        if n >= length:                    # 若大于长度,说明删除第一个节点
            self.head = self.head.getNext()# 令head指向后一个节点
        else:
            if n == 1:                     # 删除尾部节点
                for i in range(length-2):
                    pointer = pointer.getNext()
                pointer.setNext(None)      # 令尾部节点为None
            else:                          # 删除中间节点
                for i in range(length-n-1):
                    pointer = pointer.getNext()
                pointer.setNext(pointer.getNext().getNext()) #指向下一个的下一个节点
        return self.head

if __name__ == '__main__':

    mylb = DeleteNNode()
    mylb.add(9)
    mylb.add(1)
    mylb.add(5)
    mylb.add(4)

    mylb.delete_n_node(1)
    print([ele for ele in mylb.show()])
2、进阶思路

  利用两个间隔长度为n的指针,整体往前遍历,直到最后一个节点。则前面指针所指的就是待删除的节点。

代码
# -*- coding: utf-8 -*-
# ======================================================
# @Time    : 2021/01/11
# @Author  : lele wu
# @Email   : 2541612007@qq.com
# @File    : delete_n_nodeV2.py
# @Comment:  
# ======================================================

'''
题目描述:
    给定一个链表,删除链表中倒数第n个节点,并且返回头结点.且扫描一次
基本思路:
    用双指针的思想。先让一个指针往前走n个位置。
'''
from lianbiao import lianbiao

class DeleteNNode(lianbiao):
    def __init__(self):
        super(DeleteNNode, self).__init__()
    def delete_n_node(self,n):
        left = right = self.head
        # 让right指针往前移动n个位置
        si = 0
        while si < n:
            right = right.getNext()
            si += 1
        if right == None:           # 若right == None,说明删除第一个节点
            self.head = self.head.getNext()
            return self.head
        # 当前 right != None,则将两个指针往前移动至链表末尾
        while right.getNext() != None:#
            left = left.getNext()
            right = right.getNext()
        if n==1:                    # 删除末尾节点
            left.setNext(None)
        else:                       # 若删除中间节点
            left.setNext(left.getNext().getNext())
        return self.head

if __name__ == '__main__':

    mylb = DeleteNNode()
    mylb.add(9)
    mylb.add(1)
    mylb.add(5)
    mylb.add(4)

    mylb.delete_n_node(2)
    print([ele for ele in mylb.show()])
总结

a. 删除链表节点只需注意: 头结点+中间节点+尾结点。三点即可。
b. 在进阶中,两个指针整体移动到末尾节点的判断语句是: while right.next() != None: 而不是 while right != None: 。