leetcode之路029 Divide Two Integers


题目大意:实现两个整数的除法,不能用乘、除、取余操作,假如溢出了,返回INT_MAX。


思路:

1、首先考虑溢出的情况,用两种:除数为0的时候,被除数为INT_MIN、且除数为-1的时候。

2、最简单的思路:由除数n得到被除数m,可以用循环加法来得到。小于的时候,则加上一个除数,同时令计数器加1,直到大于被除数时,结束,返回计数器结果。但此方法效率过低,在被除数极大,而除数很小的时候,例当被除数INT_MAX,除数为1,则需要循环INT_MAX次,是极其低下的。因此没有考虑。

3、可以考虑循环的时候,对结果进行加倍。考虑23和2,:

第一次:2+2,第二次:4+4,第三次:8+8,第四次:16+16,此时大于23,则不进行加倍。

这是,23-16=7,可以转换为7/2的子操作:

第一次:2+2,第二次:4+4,大于7,则转换为3/2,的子操作。

根据思路3所解释的方法,可以大大降低复杂度。

在实现的时候,用了两种不同的形式,原因在于,我认为在第一轮循环过程中,计算的结果对于后面的循环求解有用,这样就可以减少计算的时间,因此用数组将除数的倍乘结果:2*n,4*n,8*n,16*n,32*n...保存了下来。

但实现得比较复杂,提交运行的时间为16ms:

class Solution {
public:
    int divide(int dividend, int divisor) {
        bool flag=false;
		if(divisor==0)
			return INT_MAX;
		else if((dividend>0&&divisor<0)||(dividend<0&&divisor>0))
			flag=true;
		long long divi_d,divi_s;
		divi_d=abs((long long)dividend);
		divi_s=abs((long long)divisor);
		if(divi_s>divi_d)
			return 0;
		long long m=divi_s;
		long long i=1;
		vector<long long> divi_mul;
		divi_mul.push_back(divi_s);
		while(m<=divi_d)
		{
			m=divi_mul.back()+divi_mul.back();
			if(m<=divi_d)
			{
				i=i+i;
				divi_mul.push_back(m);
			}	
		}
		long long mm=i;
		long long x=divi_d-divi_mul.back();
		while(x>=divi_s)
		{	
			divi_mul.pop_back();
			if(x>=divi_mul.back())
			{
				i=i+(mm>>1);
				x=x-divi_mul.back();
			}
			mm=mm>>1;
		}
		mm=flag?-i:i;
		if(mm>INT_MAX)
			return INT_MAX;
		else
			return mm;
    }
};

看运行时间分布,发现太慢了。抱着试试的心态,尝试了不保存结果,用位运算来处理写的代码,提交后时间为8ms。应该是用加法进行倍乘操作太慢了,并且有数组的动态插入和删除操作。位移运算果然是个高效的东西,代码如下:

class Solution {
public:
    int divide(int dividend, int divisor) {
        bool flag=false;
		if(divisor==0)
			return INT_MAX;
		else if((dividend>0&&divisor<0)||(dividend<0&&divisor>0))
			flag=true;
		long long divi_d,divi_s;
		divi_d=abs((long long)dividend);
		divi_s=abs((long long)divisor);
		long long m=divi_d;
		long long i=0;
		while(m>0)
		{
			long long x=divi_s;
			long long temp=1;
			while(x<=m)
			{
				x=x<<1;
				temp=temp<<1;
			}
			m=m-(x>>1);
			i=i+(temp>>1);
		}
		i=flag?-i:i;
		if(i>INT_MAX)
			return INT_MAX;
		else
			return i;
    }
};











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值