牛客刷题-go-链表节点处理

100 阅读2分钟

T1. 链表倒数K个节点

时间复杂度复习下

在想快慢针和直接遍历得链表长度然后找节点有什么区别,想了下时间复杂度上还是有区别的,计数多n次

func FindKthToTail(pHead *ListNode, k int) *ListNode {

    // write code here

    if k <= 0 {

        return nil

    }

    fast := pHead

    slow := &ListNode{-1, pHead}

    for i := 0; i < k; i++ {

        if fast == nil {

            return nil

        }

        fast = fast.Next

    }

    for fast != nil {

        fast = fast.Next

        slow = slow.Next

    }

    return slow.Next

}

吐槽:

牛客后台是怎么算运行时间的???我这段代码和榜一代码有啥区别,我跑了100ms???

T2. 公共节点

func FindFirstCommonNode( pHead1 *ListNode ,  pHead2 *ListNode ) *ListNode {

    // write code here

    len1, len2 := getLenth(pHead1), getLenth(pHead2)

    if len1 < len2 {

        n := len2 - len1

        for ; n > 0; n-- {

           pHead2 = pHead2.Next

        }

    } else {

        n := len1 - len2

        for ; n > 0; n-- {

           pHead1 = pHead1.Next

        }

    }

    for pHead1 != pHead2 {

        pHead1 = pHead1.Next

        pHead2 = pHead2.Next

    }

    return pHead1

}

func getLenth(pHead *ListNode) int {

    cur := &ListNode{-1,pHead}

    lenth := 0

    for cur.Next != nil {

        cur = cur.Next

        lenth ++

    }

    return lenth

}

可改进:

骚操作一下

图片1.png

func FindFirstCommonNode( pHead1 *ListNode ,  pHead2 *ListNode ) *ListNode {

    p1, p2 := pHead1, pHead2

    if p1 == nil || p2 == nil {

        return nil

    }

    for p1 != p2 {

        if p1 == nil {

            p1 = pHead2

        } else {

            p1 = p1.Next

        }

        

        if p2 == nil {

            p2 = pHead1

        } else {

            p2 = p2.Next

        }

    }

    return p2

}

T3. 链表相加

旧版:

func addInList(head1 *ListNode, head2 *ListNode) *ListNode {

    // write code here

    if head1 == nil {

        return head2

    }

    if head2 == nil {

        return head1

    }

    new1 := reverse(head1)

    new2 := reverse(head2)

    newHead := ListNode{-1, nil}

    cur := &newHead //cur.Next存放新节点地址

    tag := 0

    for new1 != nil && new2 != nil { //加法运算设计不够好,代码繁琐,时间开销增大

        cur.Next = &ListNode{(new1.Val + new2.Val + tag) % 10, nil}

        if (new1.Val + new2.Val + tag) > 9 {

            tag = 1

        } else {

            tag = 0

        }

        new1 = new1.Next

        new2 = new2.Next

        cur = cur.Next

    }

    if new1 == nil && new2 == nil && tag == 1 {

        cur.Next = &ListNode{tag, nil}

    }

    for new1 != nil {

        new1 = add2(new1, cur, tag)

 

    }

    for new2 != nil {

        new2 = add2(new2, cur, tag)

    }

    return reverse(newHead.Next)

}
func reverse(head *ListNode) *ListNode {

    var pre, cur, next *ListNode

    pre = nil

    cur = head

    for cur != nil {

        next = cur.Next

        cur.Next = pre

        pre = cur

        cur = next

    }

    return pre

}
func add2(head, cur *ListNode, tag int) *ListNode {  //加法运算设计不够好导致多写一个函数来处理有一个链表已空的情况

    for head != nil {

        cur.Next = &ListNode{(tag + head.Val) % 10, nil}

        if (tag + head.Val) > 9 {

            tag = 1

        } else {

            tag = 0

        }

        cur = cur.Next

        head = head.Next

    }

    if tag == 1 {

        cur.Next = &ListNode{tag, nil}

    }

    return head

}

改进思路:

注意进行算法设计时要足够细致,想清楚再动手,否则后面改动更麻烦。加法运算部分没有仔细考虑导致加法处理繁琐,加法部分实际为new1.Val + new2.Val + tag ,三部分分别判断有无即可一个循环写完,少很多代码,且不用再另写add2()做额外处理

func addInList(head1 *ListNode, head2 *ListNode) *ListNode {

    // write code here

    if head1 == nil {

        return head2

    }

    if head2 == nil {

        return head1

    }

    new1 := reverse(head1)

    new2 := reverse(head2)

    newHead := ListNode{-1, nil}

    cur := &newHead //cur.Next存放新节点地址

    val, tag := 0, 0

    for new1 != nil || new2 != nil {

        val = tag

        if new1 != nil {

            val += new1.Val

            new1 = new1.Next

        }

        if new2 != nil {

            val += new2.Val

            new2 = new2.Next

        }

        if val > 9 {

            tag = 1

        } else {

            tag = 0

        }

        cur.Next = &ListNode{val % 10, nil}

        cur = cur.Next

    }

    if tag == 1 {

        cur.Next = &ListNode{val % 10, nil}

    }

    return reverse(newHead.Next)

 

}

func reverse(head *ListNode) *ListNode {

    var pre, cur, next *ListNode

    pre = nil

    cur = head

    for cur != nil {

        next = cur.Next

        cur.Next = pre

        pre = cur

        cur = next

    }

    return pre

}

T4. 奇偶重排

写这题时犯了个错,没对even做处理,奇数个节点时成环了

func oddEvenList(head *ListNode) *ListNode {

    // write code here

    odd := &ListNode{-1, nil}

    new1 := odd

    even := &ListNode{-1, nil}

    new2 := even

    tag := 1

    for head != nil {

        if tag == 1 {

            odd.Next = head

            odd = odd.Next

            tag = 2

        } else {

            even.Next = head

            even = even.Next

            tag = 1

        }

        head = head.Next

    }

    even.Next = nil //奇数个节点时even.Next指向了odd,链表成环

    odd.Next = new2.Next

    return new1.Next

}

T5. 删除重复节点(输入1 1 1 2,输出2)

func deleteDuplicates(head *ListNode) *ListNode {

    // write code here

    pre := &ListNode{-1, head}

    newHead := pre

    for head != nil && head.Next != nil {

        if head.Val == head.Next.Val {

            tag := head.Val

            pre.Next = head.Next.Next

            head = pre.Next

            for head != nil { //不开内循环不行啊!!!!!

                if tag == head.Val {

                    pre.Next = head.Next

                    head = head.Next

                } else {

                    break

                }

            }

        } else {

            pre = head

            head = head.Next

        }

    }

    return newHead.Next

}