leetcode-50-Pow(x, n)

实现 pow(x, n) ,即计算 x 的 n 次幂函数。

示例 1:

输入: 2.00000, 10
输出: 1024.00000

示例 2:

输入: 2.10000, 3
输出: 9.26100

示例 3:

输入: 2.00000, -2
输出: 0.25000
解释: 2-2 = 1/22 = 1/4 = 0.25

说明:

-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [−231, 231 − 1] 。

第一印象

看到这道题,我们理所当然的就想到了暴力解法,即循环n次不断乘以x。

//超出时间限制(299/304)
double myPow(double x, int n) {
	if (0 == n) {
		return 1.00000;
	}
	double result = 1.00000;
	bool flag = false;
	if (n < 0) {
		n = abs(n);
		flag = true;
	}
	while (n > 0) {
		result *= x;
		--n;
	}
	if (flag) 
		result = 1 / result;
	return result;
}

当然,我们也理所当然地超时了。

尝试解决

在看答案之前来尝试下自己解决吧。

在遇到很大的n时,大量的乘法浪费了很多时间。在算法中,我们常常可以用空间来换时间,用之前求得的数来计算后面的内容。这时我所想到的方法是将n的各个位上的数提取出来,例如n = 4396,我们可以得到一个数组NumPerBit = [6,9,3,4]。然后我们可以将x的10次方,x的100次方(用x的10次方算出),x的1000次方(用x的100次方算出)·····然后根据n的各位数的大小来循环乘以对应位的值,例如对于第i位:((x10)i)^(NumPerBit[i])。这样我们只需首先将x的10的倍数次幂的值算出,然后根据每位的值不断相乘即可。

/*
执行结果:通过
执行用时:4 ms, 在所有 C++ 提交中击败了40.59%的用户
内存消耗:6.2 MB, 在所有 C++ 提交中击败了24.89%的用户

最快的一次:
执行结果:通过
执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:6.3 MB, 在所有 C++ 提交中击败了7.75%的用户
*/
double PowSet[10];//用于保存x^10,x^100,x^1000......
int NumPerBit[10];//用于保存n每位的值

double myPow(double x, int n) {
	if (0 == n) {
		return 1.00000;
	}
	double result = 1.00000;
	bool flag = false;
	long long longN = (long long)n;
	if (longN < 0) {
		longN = abs(longN);
		flag = true;
	}
	//将n按位拆解
	int bits_n = 0;//n的位数
	//cout << "n = " << longN << endl;
	while (longN) {
		NumPerBit[bits_n] = longN % 10;
		longN /= 10;
		++bits_n;
	}
	//cout << "NumPerBit = ";
	//for (int i = 0; i < bits_n; ++i) {
	//	cout << NumPerBit[i] << "\t";
	//}	cout << endl;
	for (int i = 0; i < bits_n; ++i) {
		PowSet[i] = 1.00000;
	}
	PowSet[0] = x;
	for (int i = 1; i < bits_n; ++i) {//算出x的10^n(n = [1-9])次幂的值
		for (int j = 0; j < 10; ++j) {
			PowSet[i] *= PowSet[i - 1];
		}
	}
	//cout << "PowSet = ";
	//for (int i = 0; i < bits_n; ++i) {
	//	cout << PowSet[i] << '\t';
	//}	cout << endl;
	for (int i = 0; i < bits_n; ++i) {
		for (int j = 0; j < NumPerBit[i]; ++j) {
			result *= PowSet[i];
		}
	}
	if (flag)
		result = 1 / result;
	return result;
}

成功通过!而且在快的时候能够击败100%,可见这个方法执行速度还不错。

是时候看答案了!

快速幂算法

标答使用的是快速幂算法,其实这个方法与刚刚的方法很类似。区别主要在于快速幂是按二进制位数来进行的,而我的方法是用十进制进行的。因此我的方法对于每一位都需要循环10次,而快速幂仅仅只需要一次就行了。而且代码相对而言要简单得多。

//快速幂
double myPow(double x, int n) {
	long long LongN = (long long)n;
	bool flag = false;
	if (LongN < 0) {
		LongN = abs(LongN);
		flag = true;
	}
	double result = 1.00000;
	while (LongN) {
		result *= (LongN%2? x:1);
		x *= x;
		LongN >>= 1;
	}
	if (flag) 
		result = 1.0 / result;
	return result;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值