首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >链表-如何高效删除链表的倒数第N个节点

链表-如何高效删除链表的倒数第N个节点

作者头像
阿伟
发布2019-07-22 15:56:55
发布2019-07-22 15:56:55
1.5K00
代码可运行
举报
文章被收录于专栏:GoLang那点事GoLang那点事
运行总次数:0
代码可运行
题目

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

示例

给定一个链表: 1->2->3->4->5, 和 n = 2 当删除了倒数第二个节点后,链表变为 1->2->3->5

思考

你能尝试使用一趟扫描实现吗?(时间复杂度O(n),空间复杂度O(1))

解法一

我相信很多人都明白链表要删除一个节点的做法是把要删除的节点的前驱节点指向要删除的节点的后驱节点,则完成删除一个节点的操作,如下图所示:我们删除节点为2数据,就是如此简单

我们知道,链表不像数组那样,没有下标,要想知道链表的长度,只能从链表的头部开始遍历直到结束来统计链表的长度,我们现在知道要删除链表倒数第N个节点,我们首先想到,要是知道链表长度就好了啊,看如下代码

代码语言:javascript
代码运行次数:0
运行
复制
//定义一个链表结构体
type ListNode struct {
     Val int
     Next *ListNode
}
//删除链表中倒数第N个节点
func removeNthFromEnd(head *ListNode, n int) *ListNode {
    if head == nil{
        return nil
    }
    len := 0
    temp1,temp2 := head,head
    for temp1 != nil{
        len++W
        temp1 = temp1.Next
    }
    //倒数第n个就等正数的第(len-n)+1个
    m := len- n
    //如果m=0,则是删除链表的头节点
    if m == 0{
        //如果要删除的是头节点,则将头节点指到head.Next节点
        head = head.Next
        return head
    }
    for i:=0; i<=len-1;i++{
        //找到要删除节点的上一个节点
        //将这个节点的下一个指针指到要删除节点的下一个节点
        if i == m-1{
            next := temp2.Next
            temp2.Next = next.Next
            break;
        }
        temp2 = temp2.Next
    }
    return head
}

我们看上面的代码,对整个链表进行了两次for循环,第一次求出链表的长度,第二次用来找到要删除的倒数第n个元素,有没有更好的办法呢,只遍历一次?

解法二

解法一已经实现了我们想要的功能,我们回看上面的思考(只扫描一趟实现此功能),我们看这个问题的本质,倒数第n个就等正数的第(len-n)+1个,我们看下图:

分析上面的图声明三个变量,one,two两个指针变量,i是一个int变量,one和two指向链表的头节点,one开始遍历链表,每遍历一个节点,变量i进行加1,当变量i大于n时(就是倒数第n个,在这里n是2)也就是当one指向节点4时(变成红色),two开始移动,直到one.Next等于空遍历结束,这是我们看two是不是指向了倒数第二个节点之前的节点了。 原理很简单,利用双指针变量,前指针遍历到n时,后指针开始遍历,则for循环结束时,后指针刚好指到要删除的节点的前驱节点,看代码:

代码语言:javascript
代码运行次数:0
运行
复制
//定义一个链表结构体
type ListNode struct {
    Val int
    Next *ListNode
}
func removeNthFromEnd(head *ListNode, n int) *ListNode {
    i:=0
    one,two := head,head
    for one.Next != nil{
        i++
        if i>n{
            two = two.Next
        }
        one = one.Next
    }
    //当n是倒数最大时(也就是正数第一个),i是不会大于n的
    //这其实删除的是链表的头节点
    if i< n{
        head = head.Next
        return head
    }
    //将要删除的节点的前驱节点指向要删除的节点的后
    next := two.Next
    two.Next = next.Next
    return head
}

好了,删除链表倒数第N个节点就分享到这里,有收获的帮忙关注,转发,点赞呗,非常感谢。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 GoLang那点事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目
  • 示例
  • 思考
  • 解法一
  • 解法二
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档