看这一篇文章前需要先看一下前两篇文章
练习一个新的题目:
给定一个数N,想象只由0和1两种字符,组成的所有长度为N的字符串
如果某个字符串,任何0字符的左边都有1紧挨着,认为这个字符串达标
返回有多少达标的字符串
这个问题咋一想可能不是那么容易,但是我们列举一下前几项
先写一个递归的方法:
/**
* 黑盒方法,在前面满足条件且最后一个数是1的情况下,剩余i个数有多少个达标的
* @param i
* @return
*/
public static int f(int i) {
if(i < 1) return 0;
if(i == 1 || i == 2) return i;
//第一种可能,当前位置放1,那可能性等于f(i-1)
int p1 = f(i - 1);
//第二种可能,当前位置放0,那下一位只能放1,我们可以从i-2开始讨论f(i-2)
int p2 = f(i - 2);
return p1 + p2;
}
递归的过程非常简单,但是根据递归我们看到当n大于2的时候,第n项严格依赖于低n-1和n-2项,符合第二篇文章里写的优化成O(logN)的条件,可以优化,因为只需要递推两项,这应该是一个二维矩阵的求解问题
上代码:
package dataStructure.fibonacci;
import static dataStructure.fibonacci.FibonacciStandard.matrixPower;
import static dataStructure.fibonacci.FibonacciStandard.product;
/**
* 给定一个数N,想象只由0和1两种字符,组成的所有长度为N的字符串
*
* 如果某个字符串,任何0字符的左边都有1紧挨着,认为这个字符串达标
*
* 返回有多少达标的字符串
*/
public class HowManyStandardString {
/**
* 黑盒方法,在前面满足条件且最后一个数是1的情况下,剩余i个数有多少个达标的
* @param i
* @return
*/
public static int f(int i) {
if(i < 1) return 0;
if(i == 1 || i == 2) return i;
//第一种可能,当前位置放1,那可能性等于f(i-1)
int p1 = f(i - 1);
//第二种可能,当前位置放0,那下一位只能放1,我们可以从i-2开始讨论f(i-2)
int p2 = f(i - 2);
return p1 + p2;
}
/**
* 利用类似斐波那契数列的方法求解,时间复杂度o(logN)
* @param i
* @return
*/
public static int f2(int i) {
if(i < 1) return 0;
if(i == 1 || i == 2) return i;
/*//第一种可能,当前位置放1,那可能性等于f(i-1)
int p1 = f(i - 1);
//第二种可能,当前位置放0,那下一位只能放1,我们可以从i-2开始讨论f(i-2)
int p2 = f(i - 2);
return p1 + p2;*/
//根据递归方法计算出i = 1, 2,3 ,4的时候分别是1 2 3 5
//根据上的递归计算的过程我们可以知道这个应该是个二阶的矩阵{{a,b},{c,d}}
//|f3 f2| = |f2 f1| * base;
//|3 2| = |2 1| * base 2a + c = 3 2b +d =2
//|f4 f3| = |f3 f2| * base
//|5 3| = |3 2| * base 3a + 2c = 5 3b + 2d = 3
//根据这两个方程可以推出a = 1, b = 1 c = 1 d = 0
//也就是base是{{1, 1},{1, 1}}
//|f2(i) f2(i - 1)| = |f2(2) f2(1)| * base的i-2次方
//先计算base的n-2次方
int[][] base = {{1,1},{1,0}};
int[][] matrix = matrixPower(base, i-2);
//|f2(2) f2(1)| = {{2,1}}
int[][] matrix12 = {{2,1}};
//计算|f2(2) f2(1)|乘以base的i-2次方
matrix = product(matrix12, matrix);
//[0][0]就是f2(i)
return matrix[0][0];
}
public static void main(String[] args) {
int n = 4;
int nums = f(n);
System.out.println(nums);
int nums2 = f2(n);
System.out.println(nums2);
}
}
里面有详细的注释,不理解请私信