[LeetCode] Divide Two Integers 解题报告
2012-12-21 04:49
411 查看
Divide two integers without using multiplication, division and mod operator.
两个数的除法,但是不允许用乘、除、取余符号。
[解题思路]
如果可以用乘的话,二分搜索倒是不错的解法。
否则,只能寄希望于位符操作了。
基本思想就是把除数向左移位(×2)然后与被除数比较,直到发现仅次于被除数的那个值,减去该值后继续。也可以用递归做,这里图省事,就是一个循环了事。
[做题中的几个错误]
1. Line 8,Line 9, Line10, Line 11
一开始用的是Int,而不是Unsigned Int。带来的一个最直接的问题就是,如何处理INT_MIN(-2147483648),比如 abs(-2147483648) = -2147483648。而进位的时候也麻烦,比如1073741824<<1, 结果不是2147483648, 而是-2147483648。所以把他们全部换成unsigned Int, 以避开这种麻烦。
2. Line 11 and Line 12
刚开始的时候,两行并成一行:
unsigned int migValue = dvs,i =0;
在替换完所有的int为unsigned int以后,立即犯了一个疏忽。
在处理比如(1,2)时,返回值是16777248, 而不是0。
原因就在于,当i被改为unsigned int后,如果i==0, i--会导致i变为2147483647, 而不是-1。
所以,拆分成两行,i的定义不变,仍然为int。
3. Line 21
一开始只有 while(i>=0), 没有剪枝,当dvd ==0的时候,没必要继续循环。加一个剪枝条件。
这个题目是蛮有意思的。这种数据溢出细节的处理倒是以前没有注意过。也是第一次发现原来abs(INT_MIN)的值居然还是INT_MIN。直觉上,INT_MIN的这种特性,应该跟补码有关,但是懒得深究了。
Update 08/21/2014 重新看了一下,简单的事情搞复杂了。关于溢出的问题,直接用unsigned long就解决了,省了很多不必要的比较和判断。
两个数的除法,但是不允许用乘、除、取余符号。
[解题思路]
如果可以用乘的话,二分搜索倒是不错的解法。
否则,只能寄希望于位符操作了。
基本思想就是把除数向左移位(×2)然后与被除数比较,直到发现仅次于被除数的那个值,减去该值后继续。也可以用递归做,这里图省事,就是一个循环了事。
[code]1: int divide(int dividend, int divisor) { 2: // Start typing your C/C++ solution below 3: // DO NOT write int main() function 4: int sign = 1; 5: if(dividend ==0) return 0; 6: if(dividend <0) sign*=-1; 7: if(divisor <0) sign *=-1; 8: unsigned int dvd = dividend >0? dividend: -dividend; 9: unsigned int dvs = divisor >0? divisor: -divisor;//abs(divisor); 10: unsigned int inc[32]; 11: unsigned int migValue = dvs; 12: int i =0; 13: while(migValue > 0 && migValue <= dvd) 14: { 15: inc[i] = migValue; 16: migValue = migValue <<1; 17: i++; 18: } 19: i--; 20: unsigned int res = 0; 21: while(i>=0 && dvd!=0) 22: { 23: if(dvd >= inc[i]) 24: { 25: dvd = dvd - inc[i]; 26: res += 1<<i; 27: } 28: i--; 29: } 30: res*= sign; 31: return res; 32: }
[做题中的几个错误]
1. Line 8,Line 9, Line10, Line 11
一开始用的是Int,而不是Unsigned Int。带来的一个最直接的问题就是,如何处理INT_MIN(-2147483648),比如 abs(-2147483648) = -2147483648。而进位的时候也麻烦,比如1073741824<<1, 结果不是2147483648, 而是-2147483648。所以把他们全部换成unsigned Int, 以避开这种麻烦。
2. Line 11 and Line 12
刚开始的时候,两行并成一行:
unsigned int migValue = dvs,i =0;
在替换完所有的int为unsigned int以后,立即犯了一个疏忽。
在处理比如(1,2)时,返回值是16777248, 而不是0。
原因就在于,当i被改为unsigned int后,如果i==0, i--会导致i变为2147483647, 而不是-1。
所以,拆分成两行,i的定义不变,仍然为int。
3. Line 21
一开始只有 while(i>=0), 没有剪枝,当dvd ==0的时候,没必要继续循环。加一个剪枝条件。
这个题目是蛮有意思的。这种数据溢出细节的处理倒是以前没有注意过。也是第一次发现原来abs(INT_MIN)的值居然还是INT_MIN。直觉上,INT_MIN的这种特性,应该跟补码有关,但是懒得深究了。
Update 08/21/2014 重新看了一下,简单的事情搞复杂了。关于溢出的问题,直接用unsigned long就解决了,省了很多不必要的比较和判断。
1: int divide(int dividend, int divisor) { 2: unsigned long dvd = dividend < 0 ? -dividend : dividend; 3: unsigned long dvs = divisor < 0 ? -divisor : divisor; 4: if (dvd < dvs) return 0; 5: int sign = 1; 6: if (dividend < 0) sign *= -1; 7: if (divisor <0) sign *= -1; 8: unsigned long absDivisor = dvs; 9: int step = 0; 10: while (dvs < dvd) 11: { 12: dvs = dvs << 1; 13: step++; 14: } 15: unsigned long result = 0; 16: while (dvd >= absDivisor) 17: { 18: if (dvd >= dvs) 19: { 20: dvd -= dvs; 21: result += (unsigned long) 1 << step; 22: } 23: dvs = dvs >> 1; 24: step--; 25: } 26: return result * sign; 27: }
相关文章推荐
- [leetcode] 29. Divide Two Integers 解题报告
- LeetCode解题报告—— Swap Nodes in Pairs & Divide Two Integers & Next Permutation
- [LeetCode] Divide Two Integers 解题报告
- LeetCode: Divide Two Integers 解题报告
- [Leetcode] 29. Divide Two Integers 解题报告
- LeetCode 371.Sum of Two Integers 解题报告
- [leetcode] 371. Sum of Two Integers 解题报告
- leetCode 29.Divide Two Integers (两整数相除) 解题思路和方法
- leetcode解题方案--028--Divide Two Integers
- [leetcode] 371. Sum of Two Integers 解题报告
- [leetcode javascript解题]Divide Two Integers
- Leetcode 371. Sum of Two Integers 位运算实现加法 解题报告
- [leetcode] 371. Sum of Two Integers 解题报告
- [Leetcode] 371. Sum of Two Integers 解题报告
- 【LeetCode】371. Sum of Two Integers 解题报告(Python)
- leetcode: Divide Two Integers
- leetcode Divide Two Integers
- LeetCode 2. Add Two Numbers 解题报告
- 【LeetCode】1. Two Sum 解题报告
- LeetCode的一个题目 Divide Two Integers