惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
V
Visual Studio Blog
Last Week in AI
Last Week in AI
Stack Overflow Blog
Stack Overflow Blog
The GitHub Blog
The GitHub Blog
Recent Announcements
Recent Announcements
博客园 - Franky
D
DataBreaches.Net
B
Blog
Y
Y Combinator Blog
T
The Blog of Author Tim Ferriss
Microsoft Azure Blog
Microsoft Azure Blog
人人都是产品经理
人人都是产品经理
WordPress大学
WordPress大学
P
Proofpoint News Feed
J
Java Code Geeks
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Martin Fowler
Martin Fowler
月光博客
月光博客
宝玉的分享
宝玉的分享
Engineering at Meta
Engineering at Meta
阮一峰的网络日志
阮一峰的网络日志
F
Fortinet All Blogs
博客园 - 【当耐特】

博客园 - 古文观芷

古文观芷App搜索方案深度解析:打造极致性能的古文搜索引擎 古文观芷-拍照搜古文功能:比竞品快10000倍 推荐系统实现原理介绍 AI深度解析:实时分布式消息平台NSQ Redis多线程原理详解 redis client原理分析 分布式系统选主场景分析及实现 聊聊redis单线程为什么能做到高性能和io多路复用到底是个什么鬼 golang实现常用集合原理介绍 nsq源码分析 Go map实现原理 原子操作&普通锁&读写锁 Go channel实现源码分析 go并发调度原理学习 golang实现aes-cbc-256加密解密 PHP类和函数注释大全 最近面试遇到的Windows相关的题目 一个提高查找速度的小技巧 COM是一个更好的C++
删除单链表,你会吗?
古文观芷 · 2019-12-19 · via 博客园 - 古文观芷

删除单链表中值等于XXX的所有元素

不经意间看到了一个不同寻常的实现方法,觉得挺有意思,于是自己实现了一下,代码真的是简单明了跑得还贼快!

好,现在先在脑海中想想,你会怎么实现?这么简单,5秒钟后,你想到了解决方案,于是你决定验证你的思路,请继续往下看

定义链表节点结构如下:

type ListNode struct {
   Next  *ListNode
   Value int
}

1:最常见思路

定义一个保存上个节点的变量prev,当发现当前节点cur的值等于目标值,就将prev.next = cur.next,一直循环下去,跳过节点值等于目标值的所有节点,即删除了所有值等XXX的节点,golang代码实现如下:

func RemoveNodeNormal(head *ListNode, value int) *ListNode {
   var prev *ListNode
   for cur := head; cur != nil; cur = cur.Next {
      if cur.Value == value {
         if prev != nil {
            prev.Next = cur.Next
         } else {
            head = cur.Next
         }
      } else {
         prev = cur
      }
   }
   return head
}

这么简单,我就不做任何说明了,后面会附上完整代码和简单的单测

你的思路是这样的吗?

2:第二常见思路

我要走不寻常路,定义prev变量是不可能的,这次是不可能的,如果发现当前节点值等于目标值,就用下一个节点的值覆盖当前节点的值,当前节点的下一个节点指向下下个节点。代码实现如下:

func RemoveNodeReplace(head *ListNode, value int) *ListNode {
   cur := head
   for cur != nil && cur.Value == value {
      if cur.Next == nil {
         return nil
      }
      cur.Value = cur.Next.Value
      cur.Next = cur.Next.Next
   }
   for cur != nil {
      if cur.Next != nil && cur.Next.Value == value {
         cur.Next = cur.Next.Next
      } else {
         cur = cur.Next
      }
   }
   return head
}

3:linus喜欢的代码

linus说代码应该这样写,我就不做任何说明了,你品,你细品!!

func RemoveNode(head *ListNode, value int) *ListNode {
   for cur := &head; *cur != nil; {
      if (*cur).Value == value {
         *cur = (*cur).Next
      } else {
         cur = &(*cur).Next
      }
   }
   return head
}

完整代码如下,你可以跑着试一下: 

package main

import (
    "fmt"
)

type ListNode struct {
    Next  *ListNode
    Value int
}

func RemoveNodeNormal(head *ListNode, value int) *ListNode {
    var prev *ListNode
    for cur := head; cur != nil; cur = cur.Next {
        if cur.Value == value {
            if prev != nil {
                prev.Next = cur.Next
            } else {
                head = cur.Next
            }
        } else {
            prev = cur
        }
    }
    return head
}

func RemoveNodeReplace(head *ListNode, value int) *ListNode {
    cur := head
    for cur != nil && cur.Value == value {
        if cur.Next == nil {
            return nil
        }
        cur.Value = cur.Next.Value
        cur.Next = cur.Next.Next
    }
    for cur != nil {
        if cur.Next != nil && cur.Next.Value == value {
            cur.Next = cur.Next.Next
        } else {
            cur = cur.Next
        }
    }
    return head
}

func RemoveNode(head *ListNode, value int) *ListNode {
    for cur := &head; *cur != nil; {
        if (*cur).Value == value {
            *cur = (*cur).Next
        } else {
            cur = &(*cur).Next
        }
    }
    return head
}

func ArrayToLink(nums []int) *ListNode {
    if len(nums) == 0 {
        return nil
    }
    head := &ListNode{
        Value: nums[0],
    }
    tail := head
    for i := 1; i < len(nums); i++ {
        tail.Next = &ListNode{
            Value: nums[i],
        }
        tail = tail.Next
    }
    return head
}

func LinkToArray(head *ListNode) []int {
    var array []int
    for ; head != nil; head = head.Next {
        array = append(array, head.Value)
    }
    return array
}

func ArrayEqual(nums1, nums2 []int) bool {
    if len(nums1) != len(nums2) {
        return false
    }
    for i := 0; i < len(nums1); i++ {
        if nums1[i] != nums2[i] {
            return false
        }
    }
    return true
}

func main() {
    tests := []struct {
        nums  []int
        value int
        res   []int
    }{
        {
            []int{},
            1,
            []int{},
        },
        {
            []int{1},
            1,
            []int{},
        },
        {
            []int{1, 2},
            1,
            []int{2},
        },
        {
            []int{1, 2},
            2,
            []int{1},
        },
        {
            []int{1, 2, 1, 3, 1, 4, 1, 1, 1, 1, 1},
            1,
            []int{2, 3, 4},
        },
        {
            []int{1, 2, 3, 2, 4, 2},
            2,
            []int{1, 3, 4},
        },
        {
            []int{3, 1, 3, 2, 3, 4, 3},
            3,
            []int{1, 2, 4},
        },
        {
            []int{4, 1, 4, 2, 4, 3, 4, 4, 4, 4, 4},
            4,
            []int{1, 2, 3},
        },
    }

    for _, test := range tests {
        head := ArrayToLink(test.nums)
        head = RemoveNode(head, test.value)
        array := LinkToArray(head)
        fmt.Println(ArrayEqual(array, test.res))
    }
}

如果你对算法感兴趣,可以看看我刷的LeetCode:https://github.com/chentaihan/leetcode