11

golang链表理解、递归

 4 years ago
source link: https://studygolang.com/articles/27737
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1、不使用递归

a. 链表间运算(逐位相加)

leetcode题目 示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)

输出:7 -> 0 -> 8

原因:342 + 465 = 807

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {    
    //副本
    node1 := l1
    node2 := l2
    //初始链表节点,指针才能与nil相比较
    headNode := &ListNode{
        Val: 0,
        Next: nil,
    }
    nowNode := headNode
    //溢出位
    flag := 0
    for (node1 != nil) || (node2 != nil) {
        v1 := 0
        if node1 != nil {
            v1 = node1.Val
            node1 = node1.Next
        }
        v2 := 0
        if node2 != nil {
            v2 = node2.Val
            node2 = node2.Next
        }

        sv := v1 + v2 + flag
        if sv < 10 {
            flag = 0
        }else{
            sv = sv - 10
            flag = 1
        }        
        //1. 副本找到最新节点 的指针,逐个连接
        if nowNode.Next != nil {
            nowNode = nowNode.Next
        }
        //2. 新建插入节点 的指针
        join := &ListNode{ Val: sv, Next: nil, }
        //3. 替换空指针
        nowNode.Next = join
    }

    //数据有溢出位
    if flag == 1 {
        join := &ListNode{ Val: 1, Next: nil, }
        nowNode = nowNode.Next
        nowNode.Next = join
    }
    return headNode.Next
}

小结&注意:

  • 副本的拷贝:指针传递,避免遍历迭代时污染源数据;
  • 锚点:核心,新节点添加到当前的next,如果next有了、下个next;

nowNode := headNode || if nowNode.Next != nil { nowNode = nowNode.Next }

b. 链表合并、排序

示例:

输入:

[

1->4->5,

1->3->4,

2->6

]

输出:1->1->2->3->4->4->5->6

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func mergeKLists(lists []*ListNode) *ListNode {
    headNode := &ListNode{
        Val: 0,
        Next: nil,
    }
    nowNode := headNode
    //合并,搜集排序值到slice
    var s []int
    for _,nodes := range(lists) {
        for nodes != nil {
            if nowNode.Next!=nil {
                nowNode = nowNode.Next
            }
            nowNode.Next = &ListNode{
                Val: nodes.Val,
                Next: nil,
            }
            s = append(s, nodes.Val)
            nodes = nodes.Next
        }
    }
    comNode := headNode.Next
    //排序
    newHeadNode := &ListNode{
        Val: 0,
        Next: nil,
    }
    nowNode = newHeadNode
    for i:=0; i<len(s)-1; i++ {
        for j:=i+1; j<len(s); j++ {
            if s[i]>s[j] {
                temp := s[i]
                s[i] = s[j]
                s[j] = temp                
            }
        }
    }
    //重新组合
    for i:=0; i<len(s); i++ {
        for {
            if comNode.Val == s[i] {
                nowNode.Next = &ListNode{
                    Val: comNode.Val,
                    Next: nil,
                }
                nowNode = nowNode.Next
                break;
            }
            //指针回拨
            if comNode.Next==nil {
                comNode = headNode.Next
            }else{
                comNode = comNode.Next
            }
        }
    }
    return newHeadNode.Next
}

小结:

  • 核心:副本和锚点。

2、正向递归、反向递归

a. 斐波那契数列

正向递归:

每项等于前2项之和 公式f[n]=f[n-1]+f[n-2]

func fibonacci(n int) int {
    if n=1 {
        return 0
    } else if n= 2 {
        return 1
    } else {
        return fibonacci(n-2) + fibonacci(n-1)
    }
}
fibonacci(10)

b. 猴子吃桃

反向递归 问题

有一堆桃子,猴子第一天吃了其中的一半,并在多吃了一个。以后猴子每天都吃其中的一半,然后再多吃一个,当到第10天时,发现只有一个桃子了。问题:最初共有多少个桃子?

func has_peach(n int) int {
    if n=10 { 
        return 1 
    } else { 
        return (has_peach(n+1)+1) * 2 
    }    
}
has_peach(1)

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK