剑指 Offer II 001. 整数除法
结果
执行结果:通过显示详情〉
执行用时:1 ms ,在所有Java提交中击败了 64.49%的用户
内存消耗:38.9 MB ,在所有Java提交中击败了50.17%的用户
通过测试用例:992/992
花费了一天时间解决。
思路
首先,边界问题:[ − 2 31 -2^{31} −231, 2 31 − 1 2^{31}-1 231−1],即[-2147483648, 2147483647],负数比正数多一个,负转正时会出问题,因此都转为负数来处理。
其次,关于计算思路,我有两种:
-
一种是蠢办法,一直减那个除数,会超时
-
另一种是
从除数出发,一直叠加,每次在上一次的基础上叠加,并使用一个数组(栈)来记录。
加到顶以后,又从栈的最高层慢慢减下来,并折算次数,这个次数和栈的下标有关。
实现难处:各种边界,相互牵扯的映射关系使得调试很久。
code
class Solution {
//都当成负数处理,就不会有负转正的溢出错误
public int divide(int a, int b) {
//判断答案正负号
boolean flag = (a>0&&b>0)||(a<0&&b<0)?true:false;
//排除边界和一些特定情况
if(a == -2147483648){
if (b==1){
// System.out.println("xxx");
return -2147483648;
}
else if(b==-1) return 2147483647;//溢出
}
if (b == -2147483648){
if(a == -2147483648) return 1;
else return 0;
}
// System.out.println(a+" "+b);
//把a、b转成负数
if (a > 0) a = -a;
if (b > 0) b = -b;
// System.out.println(a+" "+b);
if (a>b) return 0;
// 计算其他非0情况
int[] divideStack = new int[32]; //0号位不放
int divideNum = b; //算子默认从b的最小值开始
divideStack[1] = divideNum;
int divideStackIndex = 1;
int count = 1; //计算次数
//算子叠加
while(true){
divideNum = divideNum+divideNum;
if (divideNum > a && divideNum<0){
divideStackIndex++;
divideStack[divideStackIndex] = divideNum;
}else break;
}
count =(int) Math.pow(2,divideStackIndex-1);
// for (int d:divideStack){
// System.out.println(d);
// }
// System.out.println(divideNum +"\t" + divideStack[divideStackIndex] +"\t"+divideStackIndex+ "\t" +count);
a = a - divideStack[divideStackIndex];
//算子衰减 从最大算子开始减 因为此时剩余的数比最大算子大,但是小于2倍最大算子
while(divideStackIndex>0 ){
int temp = a - divideStack[divideStackIndex];
if (temp <= b || temp==0){
count = count + (int)Math.pow(2,divideStackIndex-1);
a = temp;
}else if (temp > b && temp <0 ){
count++;
}
// System.out.println(a+"\t"+divideStack[divideStackIndex]+"\t"+divideStackIndex+ "\t"+count);
divideStackIndex--;
}
return flag?count:-count;
}
}