剑指Offer 数值的整数次方(十二)

题目描述
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。保证base和exponent不同时为0。无需考虑越界情况。

实现思路

  • 方法一:常规的for循环遍历,时间复杂度为O(n)。
  • 方法二(较好理解):二分幂,时间复杂度为O(logn)。比如:求220,只需要递归求210,25,22,21,20即可,因为210*210=220,25*25 = 210,(22*22)*2 = 25,21*21 = 22,(20*20)*2 = 21,20 = 1(递归终止条件)。可得到以下递推公式:
    b a s e e x p o n e n t = { b a s e e x p o n e n t / 2 ∗ b a s e e x p o n e n t / 2 base%2 = 0 b a s e ∗ b a s e e x p o n e n t / 2 ∗ b a s e e x p o n e n t / 2 base%2 = 1 base^{exponent}= \begin{cases} base^{exponent/2} * base^{exponent/2}& \text{base\%2 = 0}\\ base*base^{exponent/2} * base^{exponent/2}& \text{base\%2 = 1} \end{cases} baseexponent={baseexponent/2baseexponent/2basebaseexponent/2baseexponent/2base%2 = 0base%2 = 1
  • 方法三:快速幂,时间复杂度为O(logn)。最好配合下面的快速幂代码来理解,exponent每次迭代减半,幂数为偶数累乘base,即base *= base,幂数为奇数同时还累乘结果,即result *= base,注:result初始化为1。为什么要这样乘呢?比如:求220,20的二进制为:10100 = 22 + 2 4 = 4 + 16,有220 = 24 * 216。220(幂数为偶数执行base *= base,得base2),210(幂数为偶数执行base *= base,得base4),25(可以看到前面执行了两组base *= base,刚好就是base4 = 24。幂数为奇数执行result *= base,base *= base。此时result = 24,base = base8),22(幂数为偶数执行base *= base,得base16),21(可以看到前面执行了四组base *= base,刚好得到base16 = 216。幂数为奇数执行result *= base,base * = base。此时result = 24 * 216 = 220,base的值无需再管),20(幂数为0,跳出循环的条件)。

代码实现

二分幂实现:

	public double Power(double base, int exponent) throws Exception
	{
		//处理特殊情况
		if(base == 0 && exponent == 0)throw new Exception("base和exponent不能同时为0");
		if(base == 0)return 0;
		if(exponent == 0)return 1;
		
		
		double result = 0;
		result = Power(base, Math.abs(exponent) / 2);  //递归求解,这里exponent取绝对值,为了避免当exponent为负数时,每个递归的result都要被1除。
		if(exponent % 2 != 0) //递归完后执行累乘,如果幂数是奇数
		{
			result = base * result * result;
		}
		else 
		{
			result = result * result;
		}


		if(exponent < 0)  //只会在第一层递归执行,处理exponent为负数的情况
		{
			result = 1 / result;
		}
		return result;
	}

快速幂实现:

	public double Power1( int base, int exponent ) throws Exception
	{
		//处理特殊情况
		if(base == 0 && exponent == 0)throw new Exception("base和exponent不能同时为0");
		if(base == 0)return 0;
		if(exponent == 0)return 1;


		double result = 1;
		boolean isNegative = false;
		if(exponent < 0)isNegative = true;
		
		exponent = Math.abs(exponent);
		while( exponent != 0 ) 
		{
			if( (exponent & 1) == 1 )//与b%2相同,判断奇偶性,奇数就累乘进结果。
			{
				result *= base;
			}
			base *= base; //累乘base
			exponent >>= 1;//与b/2相同
		}
		
		
		if(isNegative) //处理exponent为负数的情况
		{
			System.out.println(1/result);
			return 1/result;
		}
		else
		{
			System.out.println(result);
			return result;
		}
		
	}

参考:https://blog.csdn.net/tcm_zhangpeng/article/details/49737509

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值