斐波那契数列 和它的logN解法

package Fibonacci

import "testing"

/*
求菲波那切数列矩阵乘法的方法
1. 斐波那契数列的现行求解O(N)的方式非常好理解
2. 同时利用线性代数,可也以改写出另一种表示
 |F(N),F(N-1)| = |F(2),F(1)| * 某个二阶矩阵的N-2次方
3. 求出这个二阶矩阵,进而最快求出这个二阶矩阵的N-2次方


推广:矩阵的快速幂
                             | a b |
|F(3),F(2)| = |F(2), F(1)| * |     |
                             | c d |
         2a+  c = 3
         2b + d = 2

                             | a b |
|F(4),F(3)| = |F(3), F(2)| * |     |
                             | c d |

                             | a b |
|F(5),F(4)| = |F(4), F(3)| * |     |
                             | c d |



                 | a b |
|2,1| = |1, 1| * |     |
                 | c d |
        1*a + 1*c = 2
        1*b + 1&d = 1
        { a + c = 2
        { b + d = 1

 */

func f1(n int) int {   //暴力方法
	if n < 1 {
		return 0
	}
	if n == 1 || n == 2 {
		return 1
	}
	return f1(n-1) + f1(n-2)
}

func f2(n int) int {  //线性方法
	if n < 1 {
		return 0
	}
	if n == 1 || n == 2 {
		return 1
	}
	res, pre, tmp := 1, 1, 0
	for i := 3; i <= n; i++ {
		tmp = res
		res = res + pre
		pre = tmp
	}
	return res
}

func TestFib(t *testing.T)  {
	t.Log(f1(10))
	t.Log(f2(10))
	t.Log(f3(10))
}



func f3(n int) int {   // 矩阵方法
	if n < 1 {
		return 0
	}
	if n == 1 || n == 2 {
		return 1
	}

	base := [][]int{
		{1,1},
		{1,0},
	}
	res  := matrixPower(base, n-2)
	return res[0][0] + res[1][0]
}


func matrixPower(m [][]int,p int) [][]int {
	res := make([][]int,len(m))
	for k := range res {
		res[k] = make([]int,len(m[k]))
	}
	for i := 0; i < len(res); i++ {
		res[i][i] = 1
	}
	//res = 矩阵中的1
	tmp := m // 矩阵1次方
	for ;p != 0 ; p >>= 1 {
		if p & 1 != 0 {
			res = muliMatrix(res,tmp)
		}
		tmp = muliMatrix(tmp,tmp)
	}
	return res
}


// 两个矩阵乘完之后的结果返回
func muliMatrix(m1, m2 [][]int) [][]int {
	res := make([][]int,len(m1))
	for k := range res {
		res[k] = make([]int,len(m2[0]))
	}
	for i := 0; i < len(m1); i++ {
		for j := 0; j < len(m2[0]); j++ {
			for k := 0; k < len(m2); k++ {
				res[i][j] += m1[i][k] * m2[k][j]
			}
		}
	}
	return res
}

/*
推广

满足 F(n) = C1F(n-1) + C2F(n-2) +... + CZF(n-k)   
可以控制在 logN级别

奶牛问题
农场第一年  1只
每只母牛   1年可以产 1只母奶牛
小母牛 3年能开始生

满足递推公式
    F(N) = F(N-1) + F(N-3)


 */

/*
上楼梯  n层台阶
人 一次 1步,2步,5步
f(n) = f(n-1) + f(n-2) + f(n-5)
 */


/*
题目四
给定一个数 N,想象只由0和1两种字符组成的所有长度为N的字符串
如果某个字符串,任何0字符的左边都有1紧挨着,认为这个字符串达标
返回有多少达标的字符串

N = 1
     "0" ”1“   1个
N = 2 "00" "01" "10" "11"   2个
N = 3 "000" "001" "010" "011" "100" "101" "110" "111" 3个

f(i) 枚举0位置 下位置不能填0 只能填1
斐波那契问题,从左往右的尝试
 */

/*
区域  2 * N
给你 1 * 2的瓷砖,有多少种方法
 */

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

metabit

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值