• 斐波那契数列


    ##题目描述 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。 n<=39

    思路

    1. 递归(函数栈调用消耗太高)
      时间复杂度O(2^n),空间复杂度O(n)。

    2. 使用循环替换递归
      时间复杂度O(n),空间复杂度O(1)。

    3. 动态规划
      时间复杂度O(n),空间复杂度O(1)。

    4. 矩阵快速幂


      时间复杂度O(lgn),空间复杂度O(1)。

    递归算法

    public class Solution {
        public int Fibonacci(int n) {
            if(n < 0)    return 0;
            if(n < 2)    return n;
            return Fibonacci(n-1)+Fibonacci(n-2);
        }
    }
    

    循环算法

    public class Solution {
        public int Fibonacci(int n) {
            int a = 0, b = 1, c = 1;
            while(n-- > 0) {
                a = b;
                b = c;
                c = a + b;
            }
            return a;
        }
    }
    

    动态规划

    public class Solution {
        public int Fibonacci(int n) {
            int[] dp = new int[] {0, 1};
            while(n-- > 0) {
                dp[1] = dp[0] + dp[1];
                dp[0] = dp[1] - dp[0];
            }
            return dp[0];
        }
    }
    

    矩阵快速幂

    class Solution {
        private int[][] matmul(int[][] a, int[][] b, int m, int n, int t) {
            int[][] tmp = new int[m][n];
            for(int i = 0; i < m; i++) {
                for(int j = 0; j < n; j++) {
                    tmp[i][j] = 0;
                    for(int k = 0; k < t; k++) {
                        tmp[i][j] += a[i][k] * b[k][j];
                    }
                }
            }
            return tmp;
        }
        
        public int Fibonacci(int n){
            if(n < 1)     return 0;
            if(n == 1)    return 1;
            int[][] matT = new int[][] {{1, 1}, {1, 0}};
            int[][] fibT = new int[][] {{1}, {0}};
            while(n > 1){
                // 二进制转换,最高位1用最终快速幂矩阵,其余位1用当前幂矩阵
                if(n%2 == 1){
                    fibT = matmul(matT, fibT, 2, 1, 2);
                }
                matT = matmul(matT, matT, 2, 2, 2);
                n /= 2;
            }
            fibT = matmul(matT, fibT, 2, 1, 2);
            return fibT[1][0];
        }
    }
    

    简单快速幂求2的n次方

    class Solution {
        public long pow(int n) {
            long ans = 1, base = 2;
            while(n > 0) {
                if(n%2 == 1) {
                    ans = (ans * base) % 1000000007;
                }
                base = (base * base) % 1000000007;
                n >>= 1;
            }
            return ans;
        }
    }
    

    笔记

    1.快速幂余项的个数联想二进制权重
    2.循环实现,三次赋值,一次加法
    dp实现,两次赋值,一次加法,一次减法
    后者效率未见得高
    3.尾递归优化

  • 相关阅读:
    Echarts 实现中国地图并轮播指定的地区?
    Linux安装Zookeeper
    初遇携程apollo配置中心
    eclipse安装lombok
    依赖layui form模块 复选框tree插件(拓展可根据属性单选还是多选,数据反选)
    centos7环境下mysql5.7的安装与配置
    中文算数验证码(加减乘除)
    获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址;
    jdk自带的MD5进行数据的加密与解密
    MyBatis-plus 代码生成器
  • 原文地址:https://www.cnblogs.com/ustca/p/12312521.html
Copyright © 2020-2023  润新知