第一章 大数问题

刷题第一站

29. 两数相除

由于整数会有越界,因此用负数保存下一切。这个是可以得到正确结果的!
但是由于这里是一个一个减的,超时了。

  1. class Solution {
  2. public int divide(int dividend, int divisor) {
  3. int flag = (dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0) ? -1 : 1;
  4. if (dividend > 0) dividend = -dividend;
  5. if (divisor > 0) divisor = -divisor;
  6. int res = 0;
  7. while (dividend <= divisor) {
  8. res -= 1;
  9. dividend -= divisor;
  10. }
  11. if (flag < 0) {
  12. return res;
  13. } else {
  14. if (res == Integer.MIN_VALUE) {
  15. return Integer.MAX_VALUE;
  16. }
  17. return -res;
  18. }
  19. }
  20. }

现在用二分法和快速乘法解决!

  1. class Solution {
  2. public static int divide(int dividend, int divisor) {
  3. long result = 0;
  4. long x = dividend;
  5. long y = divisor;
  6. boolean negative = (x < 0 && y > 0) || (x > 0 && y < 0);
  7. if (x < 0) {
  8. x = -x;
  9. }
  10. if (y < 0) {
  11. y = -y;
  12. }
  13. // 由于x/y的结果肯定在[0,x]范围内,所以对x使用二分法
  14. long left = 0;
  15. long right = x;
  16. while (left < right) {
  17. long mid = left + right + 1 >> 1; // 为什么呢?看答案
  18. if (quickMulti(mid, y) <= x) {
  19. // 相乘结果不大于x,左指针右移
  20. left = mid;
  21. } else {
  22. right = mid - 1;
  23. }
  24. }
  25. result = negative ? -left : left;
  26. // 判断是否溢出
  27. if (result < Integer.MIN_VALUE || result > Integer.MAX_VALUE) {
  28. return Integer.MAX_VALUE;
  29. }
  30. return (int)result;
  31. }
  32. /**
  33. * 快速乘法
  34. *
  35. * @param a 乘数
  36. * @param b 被乘数
  37. * @return 积
  38. */
  39. public static long quickMulti(long a, long b) {
  40. long result = 0;
  41. while (b > 0) {
  42. if ((b & 1) == 1) {
  43. // 当前最低位为1,结果里加上a
  44. result += a;
  45. }
  46. // 被乘数右移1位,相当于除以2
  47. b >>= 1;
  48. // 乘数倍增,相当于乘以2
  49. a += a;
  50. }
  51. return result;
  52. }
  53. }

image.png