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)

沧浪水
97 声望12 粉丝