算法—leetcode—509

140 阅读3分钟

题目

(509). 斐波那契数
简单的斐波那契数如何做到极致?如何分析动态规划思路?

题目描述

斐波那契数,通常用F(n)表示,形成的序列称为斐波那契数列;该数列由0和1开始,后面的每一项数字都是前面两项数字的和。
也就是:

F(0) = 0,   F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.

思路

方案一

题目中已经提供算法原型
F(N) = F(N - 1) + F(N - 2)
但是此算法运算很低效,存在大量重复的运算,也就是说递归问题的三要素“重叠子问题”

方案二

算法原型还是方案一的算法,主要解决方案一中大量重复运算引起的“重叠子问题”
通过备忘录方式解决重复运算问题,以空间换时间的优化方案
代码中使用map将已经计算的结果存储起来,待下次使用时,直接读取,而不用在重复计算

方案三

斐波那契数列 通过DP table解决重叠子问题
自底向上计算的实现
我们直接从最底下,最简单,问题规模最小的f(1)和f(2)开始往上推,直到推到我们想要的答案f(20),
这就是动态规划的思路,这也是为什么动态规划一般都脱离了递归,而是由循环迭代完成计算。

方案四

斐波那契数列 通过DP table解决重叠子问题
自底向上计算的实现
我们直接从最底下,最简单,问题规模最小的f(1)和f(2)开始往上推,直到推到我们想要的答案f(20),
算法中状态转移f(n) = f(n-1)+f(n-2),计算中仅需要使用两个状态,上面都是使用map保存了所有状态
此类问题我们可以通过“状态压缩”,减少内存的浪费

代码

package leetcode

// fib
// 斐波那契数列
func fib(N int) int {
	if N == 0 {
		return 0
	}
	if N == 1 {
		return 1
	}
	return fib(N-1) + fib(N-2)
}

// fibV2
// 斐波那契数列 通过备忘录解决重叠子问题
// 自顶向下计算的实现
// 从一个规模较大的原问题比如说f(20),向下逐渐分解规模,直到f(1)和f(2) 这两个base case
func fibV2(N int) int {
	data := map[int]int{
		0: 0,
		1: 1,
	}

	// 使用递归思想解决问题
	var fib func(n int) int
	fib = func(n int) int {
		if rs, ok := data[n]; ok {
			return rs
		}
		if n == 0 || n == 1 {
			return 1
		}
		data[n] = fib(n-1) + fib(n-2)
		return data[n]
	}
	return fib(N)
}

// fibV3
// 斐波那契数列 通过DP table解决重叠子问题
// 自底向上计算的实现
// 我们直接从最底下,最简单,问题规模最小的f(1)和f(2)开始往上推,直到推到我们想要的答案f(20),
// 这就是动态规划的思路,这也是为什么动态规划一般都脱离了递归,而是由循环迭代完成计算
func fibV3(N int) int {
	data := map[int]int{
		0: 0,
		1: 1,
	}
	if _, ok := data[N]; ok {
		return data[N]
	}
	for i := 2; i <= N; i++ {
		data[i] = data[i-1] + data[i-2]
	}
	return data[N]
}

// fibV3
// 斐波那契数列 通过DP table解决重叠子问题
// 自底向上计算的实现
// 我们直接从最底下,最简单,问题规模最小的f(1)和f(2)开始往上推,直到推到我们想要的答案f(20),
// 算法中状态转移f(n) = f(n-1)+f(n-2),计算中仅需要使用两个状态,上面都是使用map保存了所有状态
// 此类问题我们可以通过“状态压缩”,减少内存的浪费
func fibV4(N int) int {
	if N == 0 {
		return 0
	}
	if N == 1 || N == 2 {
		return 1
	}
	// 状态压缩,当前算法仅需要前两个值,不需要将所有状态保存下来,可以节省内存空间
	pre, cur := 1, 1
	for i := 3; i <= N; i++ {
		sum := pre + cur
		pre = cur
		cur = sum
	}
	return cur
}

参考

来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/fi…
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。