本文共 2015 字,大约阅读时间需要 6 分钟。
请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。
现有一个链表 – head = [4,5,1,9],它可以表示为: 示例 1:输入: head = [4,5,1,9], node = 5
输出: [4,1,9] 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
示例 2:
输入: head = [4,5,1,9], node = 1
输出: [4,5,9] 解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.
说明:
题目要求中已经限定得很死,传入的是需要删除的节点,那么方法就很简单了。
但在实际项目中写删除函数,还是要考虑很多东西的,比如内存泄漏、前后指针等。
方法一:
执行用时 :4 ms, 击败了79.65%的用户 内存消耗 :2.9 MB, 击败了100.00%的用户func deleteNode1(node *ListNode) { node.Val = node.Next.Val node.Next = node.Next.Next}
方法二:
执行用时 :0 ms, 击败了7100.00%的用户 内存消耗 :2.9 MB, 击败了33.33%的用户func deleteNode2(node *ListNode) { *node = *(node.Next)}
这道题初做很难理解,什么玩意儿,明明要删值为5的节点,怎么传入函数的不是值,却是个节点?前后都没有。。。
注意:题目中的函数参数node
是个节点,那么这个节点是啥?其实就是需要删除的节点。这道题里我们并不需要知道Val
是什么,这是出题平台的事。
我试着将整个删除流程写了一下,希望能帮助大家更好理解是具体是如何实现的。
package mainimport "fmt"type ListNode struct { Val int Next *ListNode}func main() { // 预置切片,待会儿生成单链表要用 head := []int{ 4, 5, 1, 9} // 待删除节点所含的Val值 node := 5 // 分配内存空间 var ln = new(ListNode) // 头指针 listHead := ln // 创建单链表 for i := 0; i < 4; i++ { // Val赋值 ln.Val = head[i] // i<3这个条件可以不给,只不过这样的话最后一个节点的Next不是nil,多占用了一份内存空间 if i < 3 { // 给下一个节点分配一个内存空间 ln.Next = new(ListNode) // 将本次ln的内存地址改到下一个的Next上 ln = ln.Next } } // 输出完整 ln = listHead // 循环四次,每次显示后ln都指向到下一个ln的指针去 for i := 0; i < 4; i++ { fmt.Println(ln.Val) ln = ln.Next } fmt.Print("重置ln,准备删除... ") // 删除某一个节点 ln = listHead for i := 0; i < 4; i++ { if ln.Val == node { // ============================================== // 完成本题需要的操作,传入的不是Val,而是ln(*ListNode) // ============================================== deleteNode1(ln) // 完成修改后跳出循环 break } ln = ln.Next } fmt.Println("...删除结束,重置ln") // 输出删除后的单链表 ln = listHead for i := 0; i < 3; i++ { fmt.Println(ln.Val) ln = ln.Next }}func deleteNode1(node *ListNode) { node.Val = node.Next.Val node.Next = node.Next.Next}
输出结果
4
5 1 9 重置ln,准备删除… …删除结束,重置ln 4 1 9
《》
《》
转载地址:http://atkpi.baihongyu.com/