校招算法笔面试 | 校招笔面试真题-上高楼

校招算法题:斐波那契变种求解

题目## 题目

题目链接

解题思路

这是一个斐波那契数列的变种问题,使用矩阵快速幂来解决。关键点:

  1. 递推关系

    • f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(n) = f(n-1) + f(n-2) f(n)=f(n1)+f(n2)
    • 可以使用矩阵快速幂优化时间复杂度
  2. 矩阵转换

    • 使用 2 × 2 2\times 2 2×2 矩阵进行状态转移
    • 注意矩阵下标从 1 1 1 开始
  3. 取模运算

    • 所有运算都需要取模,防止溢出
    • mod = 1000000007

代码

class GoUpstairs {
public:
    #define i64 long long
    const int mod = 1e9+7;
    
    vector<vector<i64>> ksm_mar(vector<vector<i64>>A, vector<vector<i64>>B) {
        vector<vector<i64>>C(3, vector<i64>(3, 0));
        for(int i = 1; i <= 2; i++) {
            for(int j = 1; j <= 2; j++) {
                for(int k = 1; k <= 2; k++) {
                    C[i][j] = (C[i][j] + (A[i][k] * B[k][j]) % mod) % mod;
                }
            }
        }
        return C;
    }
    
    vector<vector<i64>> cul(vector<vector<i64>>A, vector<vector<i64>>B) {
        vector<vector<i64>>C(3, vector<i64>(3, 0));
        for(int i = 1; i <= 2; i++) {
            for(int j = 1; j <= 1; j++) {
                for(int k = 1; k <= 2; k++) {
                    C[i][j] = (C[i][j] + (A[i][k] * B[k][j]) % mod) % mod;
                }
            }
        }
        return C;
    }
    
    int countWays(int n) {
        if(n == 0) return 1;
        
        vector<vector<i64>>A(3, vector<i64>(3, 0));
        A[1][2] = 1;
        A[2][1] = 1;
        A[2][2] = 1;
        
        vector<vector<i64>>ans(3, vector<i64>(3, 0));
        ans[1][1] = 1;
        ans[2][1] = 2;
        
        n--;
        while(n) {
            if(n & 1) ans = cul(A, ans);
            A = ksm_mar(A, A);
            n >>= 1;
        }
        return ans[1][1];
    }
};
import java.util.*;

public class GoUpstairs {
    private static final int mod = 1000000007;
    
    private long[][] ksm_mar(long[][] A, long[][] B) {
        long[][] C = new long[3][3];
        for(int i = 1; i <= 2; i++) {
            for(int j = 1; j <= 2; j++) {
                for(int k = 1; k <= 2; k++) {
                    C[i][j] = (C[i][j] + (A[i][k] * B[k][j]) % mod) % mod;
                }
            }
        }
        return C;
    }
    
    private long[][] cul(long[][] A, long[][] B) {
        long[][] C = new long[3][3];
        for(int i = 1; i <= 2; i++) {
            for(int j = 1; j <= 1; j++) {
                for(int k = 1; k <= 2; k++) {
                    C[i][j] = (C[i][j] + (A[i][k] * B[k][j]) % mod) % mod;
                }
            }
        }
        return C;
    }
    
    public int countWays(int n) {
        if(n == 0) return 1;
        
        long[][] A = new long[3][3];
        A[1][2] = 1;
        A[2][1] = 1;
        A[2][2] = 1;
        
        long[][] ans = new long[3][3];
        ans[1][1] = 1;
        ans[2][1] = 2;
        
        n--;
        while(n > 0) {
            if((n & 1) == 1) ans = cul(A, ans);
            A = ksm_mar(A, A);
            n >>= 1;
        }
        return (int)ans[1][1];
    }
}
class GoUpstairs:
    def ksm_mar(self, A, B):
        mod = 1000000007
        C = [[0 for i in xrange(3)] for i in xrange(3)]
        for i in xrange(1, 3):
            for j in xrange(1, 3):
                for k in xrange(1, 3):
                    C[i][j] = (C[i][j] + (A[i][k] * B[k][j]) % mod) % mod
        return C
    
    def cul(self, A, B):
        mod = 1000000007
        C = [[0 for i in xrange(3)] for i in xrange(3)]
        for i in xrange(1, 3):
            for j in xrange(1, 2):
                for k in xrange(1, 3):
                    C[i][j] = (C[i][j] + (A[i][k] * B[k][j]) % mod) % mod
        return C
    
    def countWays(self, n):
        if n == 0:
            return 1
            
        mod = 1000000007
        A = [[0 for i in xrange(3)] for i in xrange(3)]
        A[1][2] = 1
        A[2][1] = 1
        A[2][2] = 1
        
        ans = [[0 for i in xrange(3)] for i in xrange(3)]
        ans[1][1] = 1
        ans[2][1] = 2
        
        n -= 1
        while n:
            if n & 1:
                ans = self.cul(A, ans)
            A = self.ksm_mar(A, A)
            n >>= 1
        
        return ans[1][1]

算法及复杂度

  • 算法:矩阵快速幂
  • 时间复杂度: O ( log ⁡ n ) \mathcal{O(\log n)} O(logn),使用快速幂优化
  • 空间复杂度: O ( 1 ) \mathcal{O(1)} O(1),只使用了常数额外空间

题目链接

解题思路

这是一个斐波那契数列变种问题。关键点:

  1. 递推关系

    • f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(n) = f(n-1) + f(n-2) f(n)=f(n1)+f(n2)
    • 到达第 n n n 级的方法 = 从 n − 1 n-1 n1 级跨1步 + 从 n − 2 n-2 n2 级跨2步
  2. 数组存储

    • 直接初始化数组的前三个值:[0,1,2]
    • 从第四个值开始递推计算
  3. 取模运算

    • 每次计算时都进行取模,防止溢出
    • m o d = 1000000007 mod = 1000000007 mod=1000000007

代码

class GoUpstairs {
public:
    int countWays(int n) {
        vector<int> d(n);
        d[0] = 0;
        d[1] = 1;
        d[2] = 2;
        for(int i = 3; i < n; i++) {
            d[i] = (d[i-1] % 1000000007 + d[i-2] % 1000000007) % 1000000007;
        }
        return d[n-1];
    }
};
import java.util.*;
public class GoUpstairs {
    public int countWays(int n) {
        // write code here
        int[] d = new int[n];
        d[0] = 0;
        d[1] = 1;
        d[2] = 2;
        for(int i = 3; i < n; i++) {
            d[i] = (int)(((long)d[i-1] % 1000000007 + d[i-2] % 1000000007) % 1000000007);
        }
        return d[n-1];
    }
}
# -*- coding:utf-8 -*-

class GoUpstairs:
    def countWays(self, n):
        d = [0] * n
        d[0] = 0
        d[1] = 1
        d[2] = 2
        for i in xrange(3, n):
            d[i] = (d[i-1] % 1000000007 + d[i-2] % 1000000007) % 1000000007
        return d[n-1]

算法及复杂度

  • 算法:动态规划(使用数组存储)
  • 时间复杂度: O ( n ) \mathcal{O(n)} O(n),需要遍历到第 n n n
  • 空间复杂度: O ( n ) \mathcal{O(n)} O(n),需要数组存储所有中间结果
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值