博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
阅读量:6509 次
发布时间:2019-06-24

本文共 5463 字,大约阅读时间需要 18 分钟。

当我第一次看到这个题目时候我我心想不就是两数相除嘛,这么简单的题目为什么要放到 Medium 中,事实证明我当时的想法Too young,Too simple,Too naive 以至于被打脸n次,可以直接查看最后答案,中间我的思路自白可以忽略。

clipboard.png

题目大意

给两个数字,除数和被除数,在不使用乘、除、取模的方法做除法,返回两数之商

备注:

1.除数和被除数都是32位有符号整数
2.除数不为0
3.假设我们正在处理一个只能在32位有符号整数范围内存储整数的环境[−231,  231 − 1],对于这个问题如果结果溢出了,则可以返回231 − 1

解题代码

public class Solution {    /**整体思路是用减法**/    public int divide(int dividend, int divisor) {        // 符号相同用减法        if(dividend==Integer.MIN_VALUE&&divisor==-1) {            return Integer.MAX_VALUE;        }                if ((dividend ^ divisor) >= 0) {            return getQuotientUsesSubtraction(dividend, divisor);        } else {            int absDividend = Math.abs(dividend);            int absDivisor = Math.abs(divisor);            if (absDividend < 0) {                absDivisor = -absDivisor;            } else if (absDivisor < 0) {                absDividend = -absDividend;            }            return 0 - getQuotientUsesSubtraction(absDividend, absDivisor);        }    }    /**     * 使用减法获取两个数的商 除数dividend,被除数divisor     * 条件:dividend*divisor >0 且divisor>0     */    private int getQuotientUsesSubtraction(int dividend, int divisor) {        int quotient = 0;        if (dividend >= 0)            while (dividend >= divisor) {                quotient++;                dividend = dividend - divisor;            }        else {            while (dividend <= divisor) {                quotient++;                dividend = dividend - divisor;            }        }        return quotient;    }}

测试用例

用的是 junit5,如果是4或者3的胖友自己修改下

import org.junit.Assert;import org.junit.jupiter.api.DisplayName;import org.junit.jupiter.api.Test;@DisplayName("不用乘除取模运算计算除数")public class TestSolution {    @Test    @DisplayName("MIN_VALUE情况和1")    void e1() {        int out = Integer.MIN_VALUE;        Solution s = new Solution();        Assert.assertEquals(out, s.divide(Integer.MIN_VALUE, 1));    }    @Test    @DisplayName("MIN_VALUE情况和-1")    void e9() {        int out = Integer.MAX_VALUE;        Solution s = new Solution();        Assert.assertEquals(out, s.divide(Integer.MIN_VALUE, -1));    }    @Test    @DisplayName("除数是0情况")    void e2() {        int out = 0;        Solution s = new Solution();        Assert.assertEquals(out, s.divide(0, 1));    }    @Test    @DisplayName("符号相反")    void e3() {        int out = -1;        Solution s = new Solution();        Assert.assertEquals(out, s.divide(1, -1));    }    @Test    @DisplayName("符号相同")    void e4() {        int out = 1;        Solution s = new Solution();        Assert.assertEquals(out, s.divide(-1, -1));    }    @Test    @DisplayName("除数MIN_VALUE和被除数MAX_VALUE")    void e5() {        int out = -1;        Solution s = new Solution();        Assert.assertEquals(out, s.divide(Integer.MIN_VALUE, Integer.MAX_VALUE));    }    @Test    @DisplayName("除数MAX_VALUE和被除数MIN_VALUE")    void e6() {        int out = 0;        Solution s = new Solution();        Assert.assertEquals(out, s.divide(Integer.MAX_VALUE, Integer.MIN_VALUE));    }    @Test    @DisplayName("冒烟测试10,3")    void e7() {        int out = 3;        Solution s = new Solution();        Assert.assertEquals(out, s.divide(10, 3));    }    @Test    @DisplayName("冒烟测试7,-3")    void e8() {        int out = -2;        Solution s = new Solution();        Assert.assertEquals(out, s.divide(7, -3));    }}

时间和空间复杂度

clipboard.png

clipboard.png

看到上面的运行时间心里凉了大半啊!,看来还有更好的方法,有时间的话写一下最优解的思路

,此处立下flag,我要写 Part 2靠大家


初级解题思路(?‍♀️此处开始为我折腾过程不重要,可以忽略)

既然乘、除、取模都用不了就用减法吧。两数取商用减法的角度思考?就是,被除数可以减几个除数。因为题目取值范围是包含负值的所以要区分符号,相同符号则返回正数,符号相反则返回负值

第一次尝试(失败?)

  • 思路:
  1. 取两个数的绝对值
  2. 当被除数大于除数时,计算相减次数,小于时则直接返回0
  3. 当两数相同符号则返回相减次数,符号相反则返回相减次数负值
  • 代码:

    class Solution {    public int divide(int dividend, int divisor) {        int absDividend= Math.abs(dividend);        int absDivisor= Math.abs(divisor);        int quotient =0;        while(absDividend>absDivisor){            quotient++;            absDividend=absDividend-absDivisor;        }        if((dividend^divisor)>= 0){            return quotient;        }else{            return 0-quotient;        }    }}
  • 结果
    自测的两个冒烟测试用例通过,但是用例[1,1]没用通过

第二次尝试(失败?)

  • 分析失败原因
    循环的时候没有考虑相等的情况
  • 修改方式
    while(absDividend>absDivisor)改为while(absDividend>=absDivisor)
  • 修改后[1,1]用例通过,但是未通过用例[-2147483648,-1]

第三次尝试(失败?)

  • 分析失败原因
    没有考虑负数的最大值的绝对值溢出了
  • 修改方式
    修改思路
    1.符号相同的时候直接获取相减次数
    2.符号不同的时候,取两数的绝对值
    3.判断两数的绝对值是否大于0,(小于0的情况是取值为−231
    4.大于0时,返回相减次数的绝对值
    5.小于0时,将大于0的数取反数再计算相减次数,返回相减次数的反数
  • 代码

    class Solution {    public int divide(int dividend, int divisor) {        // 符号相同用减法        if ((dividend ^ divisor) >= 0) {            return getQuotientUsesSubtraction(dividend, divisor);        } else {            int absDividend = Math.abs(dividend);            int absDivisor = Math.abs(divisor);            if (absDividend < 0) {                absDivisor = -absDivisor;            } else if (absDivisor < 0) {                absDividend = -absDividend;            }            return 0 - getQuotientUsesSubtraction(absDividend, absDivisor);        }    }       private int getQuotientUsesSubtraction(int dividend, int divisor) {        int quotient = 0;        if (dividend >= 0)            while (dividend >= divisor) {                quotient++;                dividend = dividend - divisor;            }        else {            while (dividend <= divisor) {                quotient++;                dividend = dividend - divisor;            }        }        return quotient;    }}
  • 结果
    未通过用例[-2147483648,-1],但是可以处理除数或被除数为-2147483648的其他用例可以处理

第四次尝试(成功✌️)

  • 分析失败原因
    没有考虑负数最大值除以-1导致溢出
  • 修改方式
    直接将这个用例视为特殊情况处理之,直接返回整值最大

转载地址:http://ywdfo.baihongyu.com/

你可能感兴趣的文章
jQuery 选择器
查看>>
Openstack的vnc界面定制
查看>>
软考 2018年下半年卷 错题知识点记录
查看>>
仿网易邮箱5.0版UI
查看>>
winsow xp不能安装软件, 提示"中断" 是因为设置了 软件限制策略
查看>>
as3调用外部应用程序 as调用外部exe文件as3调用bat文件 未测试
查看>>
linux kernel编译配置相关
查看>>
jQuery清空标签内容--防止内存泄露
查看>>
关于 HandlerMethodArgumentResolver 类 以及 WebArgumentResolver 类 自定义解析参数
查看>>
linux-高并发与负载均衡-lvs-DR模型试验
查看>>
Lucene索引
查看>>
30个php操作redis常用方法代码例子
查看>>
设计模式:对问题行之有效的解决方式。其实它是一种思想。
查看>>
java异常—检查异常(checked exception)和未检查异常(unchecked exception)
查看>>
redis持久化方法对比分析
查看>>
紫书 习题 11-10 UVa 12264 (二分答案+最大流)
查看>>
CodeForces 614B Gena's Code
查看>>
起床继续编程
查看>>
Thrift版本管理
查看>>
数据库备份那点事儿
查看>>