分治+递归法-LeetCode1922

问题内容

基本描述

我们称一个数字字符串是好数字当它满足:(下标从 0 开始偶数下标处的数字为偶数,且奇数下标处的数字为质数(2,3,5 或 7)。
比方说,“2582” 是好数字,因为偶数下标处的数字(2 和 8)是偶数且奇数下标处的数字(5 和 2)为质数。但 “3245” 不是 好数字,因为 3 在偶数下标处但不是偶数。
给你一个整数n,请你返回长度为 n 且为好数字的数字字符串总数 。由于答案可能会很大,请你将它对 1 0 2 + 7 10^2+7 102+7 取余后返回 。
一个 数字字符串 是每一位都由 0 到 9 组成的字符串,且可能包含前导 0 。

实例

输入:n = 1
输出:5

输入:n = 4
输出:400

算法求解:分治+递归

思路

对于偶数下标处的数字,它可以为 0 , 2 , 4 , 6 , 8 0,2,4,6,8 0,2,4,6,8共计5种,而长度为 n n n的数字字符串有 ( n + 1 ) / 2 (n+1)/2 (n+1)/2个偶数下标;对于奇数下标处的数字,它可以为 2 , 3 , 5 , 7 2,3,5,7 2,3,5,7共计5种,而长度为 n n n的数字字符串有 n / 2 n/2 n/2个奇数下标。因此长度为 n n n的数字,好数字的总数为
5 ( n + 1 ) / 2 × 4 n / 2 5^{(n+1)/2} \times 4^{n/2} 5(n+1)/2×4n/2
由于 5 ( n + 1 ) / 2 5^{(n+1)/2} 5(n+1)/2 较大,为了提升速度,可以采用分治+回溯的方式来求解。具体如下:
当我们要计算 x n x^n xn时,可以先递归地计算 y = x n / 2 y=x^{n/2} y=xn/2
如果 n n n为偶数, x n = y 2 x^n=y^2 xn=y2;如果 n n n为奇数, x n = x × y 2 x^n=x\times y^2 xn=x×y2
递归的边界为 n = 0 n=0 n=0,此时 y = 0 y=0 y=0

代码

以下代码需要特别注意的是,需要使用long型,而不是int型,否则当n>=15时,结果就会因为溢出而报错。

public int countGoodNumbers(long n) {

        long mod = (long) 1e9 + 7;
        long ans = f(5,(n+1)/2, mod)*f(4,n/2, mod) % mod;
        return (int) ans;

    }
    public static long f(int x, long n, long mod){
        if (n == 0){
            return 1;
        }
        long y = f(x, n/2, mod);
        if (n%2==0){
            return y*y % mod;
        }else {
            return y*y*x % mod;
        }
    }

复杂度分析

时间复杂度: O ( l o g   n ) O(log\ n) O(log n),即递归的层数。
空间复杂度: O ( l o g   n ) O(log\ n) O(log n),即递归的层数。这是由于递归的函数调用会使用栈空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值