题目意思清晰明了:求两个数的商,不能使用乘法,除法或者求模运算等等。看似很简单的一道题,可是在排行榜上的正确率却是最低的一道,原因是情况很复杂,边界很难控制。需要考虑到的细节特别多,如:正负号,除数和被除数的取值,还有就是越界情况。其中越界情况最难考虑到,我也给拉低这道题的正确率增加了一份”功劳“,真的测试了好几遍才将条件考虑全面,我的代码中写有很多注释(大部分以测试用例形式给出)可以帮助大家分析特定情况,这类型的题目没有很强的技巧,唯一需要注意的就是”细心“。对了,还有一个问题就是如何不使用乘除法以及求模运算求商。我的思路是采用移位运算(其实是一种特殊的乘法)举个例子吧:
如 :23/4
(4<<3)= 32 > 23
(4<<2)=16 < 23
那么商在 2^2(4)~2^3(8)之间,最小为 4(第一部分)
23-4*2^2 = 23 - 16 = 7
4<<1 = 8 > 7 , 但是 4 < 7 所以可以求出第二部分的商为 1
综上所述,23/4 = 5(商为5)
如果还不理解那就参看我的代码吧,代码如下:
class Solution { public: int divide(int dividend, int divisor) { //求两个数的商 //1.被除数为0 if (divisor == 0) {//不合法的数 return 0; } //2.除数为 0 if (dividend == 0) {//除数为0 return 0; } //3.被除数为1 if (divisor == 1) { return dividend; } //4.被除数为2 else if (divisor == 2) { return dividend >> 1; } //5.考虑溢出问题,正数溢出或者负数溢出 double maxint = pow(2, 31) - 1; if (dividend - maxint > 0.000001) { dividend = int(maxint); } if (divisor - maxint > 0.000001) { divisor = int(maxint); } if(dividend < maxint*(-1) && divisor < maxint*(-1)) {// 例如:-2147483648 / -2147483648 return 1; } if (dividend < maxint*(-1)) { dividend = maxint*(-1); } if (divisor < maxint*(-1)) {//被除数越界 例如:(1~2147483647) / -2147483648 //divisor = maxint*(-1); return 0; } //6.考虑正负号 int minus = 1; //商是否为负数 if (dividend < 0 && divisor < 0) { dividend *= -1; divisor *= -1; if (divisor > dividend) { return 0; } } else { if (dividend < 0) { dividend *= -1; minus = -1; } if (divisor < 0) { divisor *= -1; minus = -1; } } if (dividend == divisor) { //例如: 1 / -1 return 1*minus; } //7.被除数为1 if (divisor == 1) { //例如: -1 / -1 return dividend; } else if (divisor == 2) { //例如: -6 / -2 return dividend >> 1; } //8.开始求商 25 / 4 -> 6 4<<2--16 25 4<<3--32 所以,商在4~8之间 int left = 0; int right = 1; int ret = 0; int mybeover = maxint / 2; while (dividend > divisor) { left = 0; right = 1; while ((divisor << right) < dividend) { if ((divisor << left) >= mybeover) { break; } ++left; ++right; } ret += 1 << left; dividend -= divisor << left; } return ret*minus; } };
代码中注释挺多的,希望不会让大家看的瞌睡来了,我的代码可能有点啰嗦,不过主要还是分细节去讨论了可能出现的情况。
时间: 2024-11-02 03:11:29