LeetCode:29.Divide Two Integers[Medium]

题目:Divide two integers without using multiplication, division and mod operator.If it is overflow, return MAX_INT.
首先,题目要求计算两个数相除的结果
其次,不能使用乘法、除法和模运算;如果结果溢出直接返回MAX_INT。

根据题目的限制,首先可能想到使用减法,循环用被除数减除数,知道小于0为止,但是这样对于很大的被除数肯定超时了(如2147483647除以1)。

可以使用移位运算,在Java中有三种移位运算

  • << : 左移运算符,num << 1,相当于num乘以2
  • >> : 右移运算符,num >> 1,相当于num除以2
  • >>> : 无符号右移,忽略符号位,空位都以0补齐
    注意运算符都在操作数的右侧

该题使用移位运算符的思路其实和使用减法相同,不过提高了效率(注意符号的处理,可以先保存符号位,然后将取两个数的绝对值计算):

  1. 每次将divisor左移shift位,得到最接近(小于)dividend的最大的数maxCloset,该数与divisor的商构成了最终商的一部分
  2. 使用dividend减去maxCloset后继续步骤1,直到dividend小于divisor

注意,对于可能出现的溢出,需要首先将操作数转换为long类型,同时程序中使用的数据类型尽量为long类型。最后类型转换前,也需要判断是否会溢出。

代码如下:

public class Solution {
    public int divide(int dividend, int divisor) {
        long dividendLong = dividend;
        long divisorLong = divisor;
        //可能的极端情况
        if(divisorLong == 0)
            return Integer.MAX_VALUE;
        if(dividendLong == 0)
            return 0;
        //保存结果商
        long trade = 0;
        int sign = 1;//计算符号位
        if((dividendLong < 0) ^ (divisorLong < 0))
            sign = -1;
        //取绝对值,如果使用int,这里可能出现溢出
        dividendLong = Math.abs(dividendLong);
        divisorLong = Math.abs(divisorLong);
        while(dividendLong >= divisorLong){
            int shift = 0;//左移位数
            long part = 1;//部分商
            while(divisorLong<<shift < dividendLong) {
                ++shift;
                part <<= 1;
            }
            if(dividendLong == divisorLong<< shift) {
            //如果相等,则直接跳出
                trade += part;
                break;
            }
            //不相等,需要向右移位,取maxCloset
            trade += part >> 1;
            dividendLong -= divisorLong << (shift-1);
        }
        //最后判断是否存在溢出
        if(trade*sign > Integer.MAX_VALUE || trade*sign < Integer.MIN_VALUE)
            return Integer.MAX_VALUE;
        else
            return (int)trade*sign;
    }
}
给定一个整数数组 nums 和一个目标值 target,要求在数组中找出两个数的和等于目标值,并返回这两个数的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历数组的所有组合,判断两个数的和是否等于目标值。如果等于目标值,则返回这两个数的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储数组中的元素和对应的索引。遍历数组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查找哈希表中是否存在这个差值。 如果存在,则说明找到了两个数的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表中。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双指针 如果数组已经排序,可以使用双指针的方法来求解。假设数组从小到大排序,定义左指针left指向数组的第一个元素,右指针right指向数组的最后一个元素。 如果当前两个指针指向的数的和等于目标值,则返回它们的索引。如果和小于目标值,则将左指针右一位,使得和增大;如果和大于目标值,则将右指针左一位,使得和减小。 继续动指针,直到找到两个数的和等于目标值或者左指针超过了右指针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问题,选择合适的方法取决于具体的应用场景和要求。如果数组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果数组较大或者需要优化时间复杂度,则哈希表或双指针方法更合适。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值