刻意练习:LeetCode实战 -- Task11. 删除链表的倒数第N个节点

C#学习 同时被 3 个专栏收录
309 篇文章 16 订阅
114 篇文章 9 订阅
167 篇文章 4 订阅

背景

本篇图文是LSGO软件技术团队组织的 第二期基础算法(Leetcode)刻意练习训练营 的打卡任务。本期训练营采用分类别练习的模式,即选择了五个知识点(数组、链表、字符串、树、贪心算法),每个知识点选择了 三个简单、两个中等、一个困难 等级的题目,共计三十道题,利用三十天的时间完成这组刻意练习。

本次任务的知识点:链表

链表(Linked List) 是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里除了存放本身数据(data fields)之外还存放其后继节点的指针(Pointer)。

使用链表结构可以克服数组需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。

链表有很多种不同的类型:单向链表,双向链表以及循环链表。


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

示例

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

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

说明

给定的n保证是有效的。

进阶

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


第一种:先求链表长度的方法

思路:先求出链表的长度len,再求出要删除结点的位置index = len - n。这样就可以从头结点开始遍历到该位置,删除该结点即可。

  • 执行结果:通过
  • 执行用时:148 ms, 在所有 C# 提交中击败了 6.77% 的用户
  • 内存消耗:24.6 MB, 在所有 C# 提交中击败了 5.43% 的用户
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public int val;
 *     public ListNode next;
 *     public ListNode(int x) { val = x; }
 * }
 */
 
public class Solution
{
    public ListNode RemoveNthFormEnd(ListNode head, int n)
    {
        int len = GetLength(head);
        int index = len - n;

        if (index == 0)
        {
            head = head.next;
            return head;
        }
        ListNode temp = head;
        for (int i = 0; i < index - 1; i++)
        {
            temp = temp.next;
        }
        temp.next = temp.next.next;
        return head;
    }

    public int GetLength(ListNode head)
    {
        ListNode temp = head;
        int i = 0;
        while (temp != null)
        {
            i++;
            temp = temp.next;
        }
        return i;
    }
}

第二种:双指针法

思路:使用两个指针,前面的指针p2先走n步,接着让后面的指针p1p2同步走,p2走到终点,p1即走到要移除的结点位置。

  • 执行结果:通过
  • 执行用时:108 ms, 在所有 C# 提交中击败了 74.84% 的用户
  • 内存消耗:24.8 MB, 在所有 C# 提交中击败了 5.43% 的用户
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public int val;
 *     public ListNode next;
 *     public ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode RemoveNthFromEnd(ListNode head, int n) {
        ListNode p1 = head;
        ListNode p2 = head;

        while (n > 0)
        {
            p2 = p2.next;
            n--;
        }

        if (p2 == null) //移除头结点
        {
            return head.next;
        }
            
        while (p2.next != null)
        {
            p2 = p2.next;
            p1 = p1.next;
        }
            
        p1.next = p1.next.next;
        return head;
    }
}

Python 语言

  • 执行结果:通过
  • 执行用时:48 ms, 在所有 Python3 提交中击败了 23.58% 的用户
  • 内存消耗:13.5 MB, 在所有 Python3 提交中击败了 7.83% 的用户
# 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:
        p1 = head
        p2 = head
        while(n>0):
            p2 = p2.next
            n-=1
            
        if(p2 is None): #移除头结点
            return head.next

        while(p2.next):
            p1 = p1.next
            p2 = p2.next
            
        p1.next = p1.next.next
        return head

来源

  • https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/

往期活动

LSGO软件技术团队会定期开展提升编程技能的刻意练习活动,希望大家能够参与进来一起刻意练习,一起学习进步!


我是 终身学习者“老马”,一个长期践行“结伴式学习”理念的 中年大叔

我崇尚分享,渴望成长,于2010年创立了“LSGO软件技术团队”,并加入了国内著名的开源组织“Datawhale”,也是“Dre@mtech”、“智能机器人研究中心”和“大数据与哲学社会科学实验室”的一员。

愿我们一起学习,一起进步,相互陪伴,共同成长。

后台回复「搜搜搜」,随机获取电子资源!
欢迎关注,请扫描二维码:

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论
请先登录 后发表评论~
©️2021 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页

打赏作者

老马的程序人生

感谢您的支持!

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值