C++刷题日记:Leetcode 50. Pow(x,n)

题目

Leetcode 50. Pow(x,n)
实现 pow(x, n) ,即计算 x 的 n 次幂函数(x^n)
在这里插入图片描述

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/powx-n
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解析

拿到手直接

class Solution {
public:
    double myPow(double x, int n) {
	return pow(x,n);
    }
};

调cmath里的pow方法。就AC了
在这里插入图片描述
不过这道题本意应该是要自己写方法
最直接的思路仅仅考虑实现,通过次数循环控制x自乘即可。这是v1版本
考虑到大量的for费时又费力
想想这道题是要求幂次,可以通过二进制移位方式来实现。可以写出v2版本代码
再想想可以通过缩小规模来实现,这是v3代码

实现

暴力求解 v1

class Solution {
public:
    double myPow(double x, int n) {
	long long N=n;
	if(N<0){
		x=1/x;
		N=-N;
	}
	double ans=1;
	for(long long i=0;i<N;i++)ans*=x;
	return ans;
    }
};

时间复杂度O(n)
空间复杂度O(1)
在这里插入图片描述
结果是没错,不过不出意外的,超出了时间限制。

按位移动法 v2

注意,起初的思路是通过对x进行按n进行移位操作,后来发现C++中的移位操作只能对int操作。也就是可以对整数实现pow,对带有小数的会失败。还是把代码放出来供参考

class Solution {
public:
    double myPow(double x, int n) {//失败,仅对整数可以实现求幂次,带小数结果错误
	if(n==0)return 1;
	if(n==1)return x;
	int res=(int)x;
	res<<=abs(n)-1;
	return n>0?(double)res:(1/(double)res);
    }

通过对计算次数减少,也就是对幂次n进行移位。可以大幅减少运算次数,并且成功AC。代码如下

class Solution {
public:
    double myPow(double x, int n) {
	if(n==0)return 1;
	if(n==1)return x;
	if(n==-1)return 1/x;
	if(n&1){
		return myPow(x*x,n>>1)*x;
	}
	return myPow(x*x,n>>1);
    }
};

在这里插入图片描述

二分思想v3

采用分治法,通过二分法实现O(log n)的时空复杂度

class Solution {
public:
double f(double x,int n){
	if(n==0)return 1;
	double half=f(x,n/2);
	return n&1==1?half*half*x:half*half;
}
    double myPow(double x, int n) {
	if(n==0||x==1)return 1;
	long long N=n;
	return N>0 ? f(x,N): 1/ f(x,-N); 
	}
};

在这里插入图片描述

迭代

妙在对幂转了2进制,从最后一位开始判断是否有做出贡献,如2^16次方。
如x^77次方,77的二进制形式对应了(1001101)中的每个1。
2^0=1
2^2=4
2^3=8
2^6=64
把这些幂次相加等于77
请添加图片描述

这里来个例子,比如x=2,n=16。指数16可以拆分为2^4次方,二进制表示形式就是(10000),程序过程如下图所示
请添加图片描述

class Solution {
public:
double ff(double x,long long n){
	double x_useful=x;
	double ans=1;
	while(n>0){
		if(n&1){
			//末位是1
			ans*=x_useful; 
		}
		x_useful*=x_useful;
		n/=2;
	}
	return ans;
}
    double myPow(double x, int n) {
    long long N=n;
	return N>=0? ff(x,N):1/ff(x,-N);
	}
};

在这里插入图片描述
时间复杂度:O(logn)
空间复杂度:O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会写程序的程序员.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值