• 删除单链表,你会吗?


    删除单链表中值等于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
    }
    这么简单,我就不做任何说明了,后面会附上完整代码和简单的单测
    你的思路是这样的吗?
    if 是 || !不是 {
        请继续往下看  
    }
     
    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  

  • 相关阅读:
    原型模式
    简单工厂模式与工厂方法模式
    监听器 Listener
    代理模式
    装饰模式
    软件设计的原则
    事务的特性和隔离级别
    JDBC事务(三)ThreadLocal绑定Connection
    JDBC事务(二)转账示例
    JDBC事务(一)
  • 原文地址:https://www.cnblogs.com/hlxs/p/12067205.html
Copyright © 2020-2023  润新知