递归

递归三要素

  1. 一个问题得解,可以分解为几个子问题的解。
  2. 这个问题与分解之后的子问题,除了数据规模不同,求解思路要完全一样。
  3. 存在递归终止条件。

递归实现步骤

  1. 根据把大问题分解为小问题得规律,找出递推公式,找到终止条件。
  2. 翻译成代码。

举例

假设有n个台阶,一步可以走1个台阶或者2个台阶,问走完n个台阶有多少种走法?

package main

import "fmt"

func Step(n int) (sum int) {

	if n <= 2 {
		return n
	}

	sum = Step(n-1) + Step(n-2)
	return
}

func main() {
	sum := Step(4)
	fmt.Println(sum)
}

注意点

堆栈溢出

原因:递归的函数调用的临时变量都存储在内存栈中,等函数执行完成返回时候才出栈,当调用次数过多,层次太深时,就造成堆栈溢出。

解决方式:可以添加全局计数,限制递归深度,触达最大深度时,直接终止退出程序,只是个饮鸩止渴方式,并不能实际解决问题。

package main

import "fmt"

var i int

func Step(n int) (sum int) {

	if i == 100 {
		panic("stack over flow .")
	}
	i++

	if n <= 2 {
		return n
	}

	sum = Step(n-1) + Step(n-2)
	return
}

func main() {
	sum := Step(100)
	fmt.Println(sum)
}

避免重复计算

递归到一定小规模数据解时候,事先离线计算把小规模解计算好,存储在一个列表表中,当递归时,先读取散列表有没有对应规模的解,有了直接取值返回,避免重复计算。

package main

import "fmt"

var i int

var HasSolvedList = make(map[int]int)


func Step(n int) (sum int) {

	if i == 100000 {
		panic("stack over flow .")
	}
	i++


	if v, ok := HasSolvedList[n]; ok  {
		//fmt.Printf("HasSolvedList n : %d\n", n)
		return v
	}


	if n <= 2 {
		return n
	}

	sum = Step(n-1) + Step(n-2)
	return
}

func main()  {
	HasSolvedList[2] = 2
	HasSolvedList[3] = 3
	HasSolvedList[4] = 5
	HasSolvedList[5] = 8

	sum := Step(20)
	fmt.Println(sum)
}

函数调用耗时多

函数调用空间复杂度高

复杂度

todo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值