斐波那契数列 和它的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的瓷砖,有多少种方法
 */

你可能感兴趣的:(数据结构与算法,线性代数,矩阵,算法)