LeetCode 面试题 08.05. 递归乘法
解法一
题解:递归
class Solution {
public:
int multiply(int A, int B) {
if (A == 0 || B == 0) return 0;
// if (A == 1) return B;
if(A>B) swap(A, B);
return multiply(A-1, B) + B;
}
};
要点:为了避免递归调用太多,造成栈溢出,当A大于B时,交换A和B的值。
解法二
题解:快速幂
- 迭代
func multiply(A int, B int) int {
class Solution {
public:
int multiply(int A, int b) {
int ret=0;
unsigned int a = A;
while(b>0){
if((b&1)==1){
ret+=a;
}
a+=a;
b>>=1;
}
return ret;
}
};
}
要点:用unsigned int是为了避免溢出问题。
- 递归
class Solution {
public:
int multiply(int a, int b) {
if(b == 0) return 0;
if(b % 2 == 0) return (multiply(a, b>>1) << 1);
else return (a + multiply(a, b-1));
}
};
快速幂
快速幂基于二分的思想,常被称为二分幂。快速幂基于两个事实:
(1)若b为奇数,则a^b = a * a^(b-1);
(2)若b为偶数,则a^b = a^(b/2) * a^(b/2)。
迭代实现
思路:
对a来说,如果把b写成二进制,b就可以写成若干二次幂的和。例如13的二进制是1101,3,2,0号位都是1,那么就可以得到 13= 2^3 +2^2 +2^0= 8+4+1,所以 a^13= a^(8+4+1)= a^8 * a^4 * a^1。
因此可得快速幂迭代写法的一般思路:
①初始化令ret=1,存放累积的结果。
②判断b的二进制末尾是否为1 (也就是判断b是否为奇数),如果是,则令ret乘上a的值。
③令a平方,并将b右移一位(也就是将b除以2)。
④只要b大于0,就返回②。
代码:
int fastPower(int a, int b)
{
int ret = 1;
while (b)
{
if (b % 2 == 1) // 如果b是奇数,需要将ret先乘a,其他操作与b为偶数的情况一样
ret *= a;
a *= a;
b >>= 1;
}
return ret;
}
递归实现
思路:
①当b是奇数的时候,a= a^(b−1) ∗a,然后b--。
②当b是偶数的时候,a= a^(b/2) ∗a^(b/2),然后b>>=1
③当b==0的时候,a=1,这也是最后递归的出口。
代码:
int fastPower(int a, int b)
{
if (b == 0) return 1;
int ret = 0;
if (b & 1)
{
ret = fastPower(a, b/2) * fastPower(a, b/2);
return ret;
}
else
{
return (a * fastPower(a, b - 1));
}
}