0
点赞
收藏
分享

微信扫一扫

《算法基础》二分快速幂

芒果六斤半 2022-03-19 阅读 60

目录

1、LeetCode——50. Pow(x, n)

2、LeetCode——372. 超级次方

3、LeetCode——343. 整数拆分


1、LeetCode——50. Pow(x, n)

思路: 

  1. 使用循环来做,x 的 n 次幂就是 n 个 x 相乘
  2. 使用二分快速幂,就是折半计算,每次把n缩小一半,直到最后为0;如果 n 为偶数的话就直接把 x 平方,如果是奇数的话,就多乘一个 x ;比如2的5次方:2 ^ 2 = 4,4 ^ 4 = 16,16 * 2 = 32;

代码及详情:

double myPow(double x, int n){
    // return pow(x,n);
    if(x == 1) return 1;
    if(x == 0) return 0;
    if(n == 0) return 1;
    if(n == 1) return x;

    // 运行超时
    // double ans = 1;
    // for(int i = 0; i < abs(n); i++){
    //     ans *= x;
    // }
    // if(n < 0) 
    //     return 1 / ans;
    // return  ans;

    // 二分快速幂
    double ans = 1.0;
    for(int i = n; i != 0; i /= 2){
        if(i % 2)
            ans *= x;
        x *= x;
    }
    return n < 0 ? 1 / ans : ans;  // 还注意一下n为负数的情况
}

2、LeetCode——372. 超级次方

 思路: 可以从前到后遍历 b 数组,计算出 a 的 b[i] 次方,因为 b 数组表示的是一个数,所以由下面的代码可以看出,每一次计算完 b[i] 后,要将 b[i] 变成 b[i] 的10次方。

a^12 = a^10 * a^2
a^112 = a^100 * a^10 * a^2

假如 a = 2, b = [1,2];
    a ^ b[0] = 2;
--> 2 ^ 10 = 1024;
    a ^ b[1] = 4;
--> 2 ^ 12 = 2 ^ 10 * 2 ^ 2 = 1024 * 4 = 4096
        

代码及详情:

long long myPow(long long a, int b){
    if(a == 1 || b == 0) return 1;
    long long ans = 1;
    for(int i = b; i != 0; i /= 2){
        if(i % 2)
            ans = ans * a % 1337;
        a = a * a % 1337;
    }
    return ans;
}
// a^12 = a^10 x a^2
// a^112 = a^100 x a^10 x a^2
// 相当于把b里面的数字来求和,同时计算出每一位的幂
int superPow(int a, int* b, int bSize){
    if(a == 1) return 1;
    long long ans = 1;
    for(int i = 0; i < bSize; i++){
        ans = myPow(ans, 10) * myPow(a, b[i]) % 1337;
    }
    return ans;
}

3、LeetCode——343. 整数拆分

 思路:用到了动态规划, n 起码可以被拆分为两个正整数(i 和 n - i),用一个数组 dp[n]来表示将正整数 n 拆分成至少两个正整数的和之后,这些正整数的最大乘积。当 n >= 2 时:

  1. 如果 n - i 不能再拆分了,那么此时的乘积就是 i * (n - i)
  2. 如果 n - i 还可以再拆分,那么此时的乘积就是 i * dp[(n - i)]

代码及详情:


int max(int a, int b){
    return a > b ? a : b;
}
int integerBreak(int n){
    /*
        dp[i] 表示将正整数 i 拆分成至少两个正整数的和之后,这些正整数的最大乘积。
        特别地,0 不是正整数,1 是最小的正整数,0 和 1 都不能拆分,因此 dp[0]=dp[1]=0.
        当 i≥2 时,假设对正整数 i 拆分出的第一个正整数是 j(1≤j<i),则有以下两种方案:
        将 i 拆分成 j 和 i-j 的和,且 i−j 不再拆分成多个正整数,此时的乘积是 j×(i−j);
        将 i 拆分成 j 和 i-j 的和,且 i−j 继续拆分成多个正整数,此时的乘积是 j×dp[i−j]。
    */
    int dp[n + 1];
    memset(dp,0,sizeof(dp));
    for(int i = 2; i <= n; i++){
        int curmax = 0;  // 为当前的最大乘积
        for(int j = 1; j < i; j++){
            curmax = max(curmax, max(j * (i - j), j * dp[i - j]));
        }
        dp[i] = curmax;
    }
    return dp[n];
}

文首图片素材取自博客:《算法零基础100讲》(第15讲) 二分快速幂_英雄哪里出来的博客-CSDN博客

举报

相关推荐

0 条评论