【LeetCode 中等题19】-- 删除链表倒数第N个节点(1)

声明

今天是LeetCode 中等第1道题,以此作为练习记录,欢迎交流。文中也会给出所参考的文章链接,感谢前辈们的总结。
(手动比心ღ( ´・ᴗ・` ))

题目

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

示例:

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

当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。

正文

思路1:

删除倒数第n个节点,换种思路就是删除正着数第 L-n+1 个节点。
找到这个节点
删除

需要知道 L:
删除第 L-n+1 个节点,就是改变 L-n 个节点的指针。指向 L-n+2 个节点。

LeetCode官方解答
两次遍历实现:
第一次遍历得到链表长度
第二次遍历找到第 L-n 个节点,改变其指针。
实现:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:

        #添加亚节点
        dummy = ListNode(0)
        # 亚节点和head关系
        dummy.next = head # 不是 head = dummy.next 
        count = 0
        p = head
        # 第一次遍历:得到链表长度
        while p:
            count += 1
            p = p.next
        
        # 第二次遍历:从哑节点开始,找到第 L-n 个节点
        q = dummy 
        count = count - n
        while count > 0:
            count -= 1
            q = q.next     # 遍历结束后,q 指向第 L -n 个节点
        # 删除第L-n+1 个节点,即 改变第L-n 个节点指针
        q.next = q.next.next
        # 返回链表地址
        return dummy.next  # 为什么需要哑节点;若链表只有头节点,则删除后dummy.next是NULL
        

为什么第二次遍历从 count - n 开始
为什么第二次遍历从  count - n 开始

代码写的过程:
先写两次遍历,其他随着补充。

思路2:
参考LeetCode 对应解答

博客Python实现

思路:
使用一次遍历。
1、p,q两个指针同时指向dummy节点
2、第一次循环:p不动,移动q,使得 p, q 两个节点之间间隔 n 个节点。
3、同时移动 p, q(每次移动相同距离),当 q 指向 NULL时,停止。
此时,p 恰好指向 要删除节点的前一个节点, 即第 L -n个节点
4、改变此时p节点的指针,删除倒数第 n 个节点。

此方法非常巧妙,还简单。

# class ListNode:
 #    def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        ####方法2
        dummy = ListNode(0)
        p, q = dummy ,dummy
        dummy.next = head
        # 第一次遍历:p 不动,q 移动到第 n+1 个节点。
        while n+1 > 0: # 循环条件怎么写
            n -= 1
            q = q.next # 循环介绍后q 指向第n+1 个节点
       
        # 第二次遍历:p,q同时移动,每次移动一个节点,当q指向NULL,停止;此时,p指向第 L-n 个节点。
        while q:
            p = p.next
            q = q.next # 遍历结束后,q指向NULL,p指向第 L-n 个节点
        # 删除第 L-n+1 个节点
        p.next = p.next.next
        return dummy.next

难点两次循环条件。

收获

总结

1、链表删除元素和删除节点区别
2、数组遍历 和 链表遍历 的框架
链表遍历:(统计链表节点数)

p = head
while p :  
	count += 1
	p = p.next 

3、代码框架:
p不动,移动q到第 n+1 个节点
p不动,移动q到第 n+1 个节点
第二次遍历:
在这里插入图片描述

发布了71 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42025376/article/details/105317997
今日推荐