• 移位操作搞定两数之商


    五一漫长的假期,外面的世界是人山人海,反而在家刷题算得上一个好的休闲方式。刚好我开始写这道题:

    Given two integers `dividend` and `divisor`, divide two integers **without** using multiplication, division, and mod operator.
    
    The integer division should truncate toward zero, which means losing its fractional part. For example, `8.345` would be truncated to `8`, and `-2.7335` would be truncated to `-2`.
    
    Return *the **quotient** after dividing* `dividend` *by* `divisor`.
    
    **Note:** Assume we are dealing with an environment that could only store integers within the **32-bit** signed integer range: `[−231, 231 − 1]`. For this problem, if the quotient is **strictly greater than** `231 - 1`, then return `231 - 1`, and if the quotient is **strictly less than** `-231`, then return `-231`.
    
     
    
    **Example 1:**
    
    

    Input: dividend = 10, divisor = 3
    Output: 3
    Explanation: 10/3 = 3.33333.. which is truncated to 3.

    
    **Example 2:**
    
    

    Input: dividend = 7, divisor = -3
    Output: -2
    Explanation: 7/-3 = -2.33333.. which is truncated to -2.

    
     
    
    **Constraints:**
    
    -   `-231 <= dividend, divisor <= 231 - 1`
    -   `divisor != 0`
    
    

    看懂题目上说的,就是不能用乘法、除法以及取余操作来算出两个给定整数的商。这个时候我想到利用移位操作来实现。
    虽然工作多年,但是真正在实际项目中用到移位操作的时候是很少的。
    逻辑移位:

    -   逻辑移位将位向左或向右移动,并在空位填充零。
    -   在左逻辑移位(<<)中,位向左移动,从右侧填充零。
    -   在右逻辑移位(>>)中,位向右移动,从左侧填充零。
    

    简单来说,如果1<<2, 就是1乘以2的2次方,以此类推。
    所以我的解法就很明确了, 处理好被除数和除数的符号,然后再通过循环里面使用移位操作计算出商的:

    
    func divide(dividend int, divisor int) int {
    	quotient := 0
    	maxInt := math.MaxInt32
    	minInt := math.MinInt32
    	if divisor == 0 || (dividend == minInt && divisor == -1) {
    		return maxInt
    	}
    
    	// determine the sign of the quotient
    	sign := -1
    	if (dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0) {
    		sign = 1
    	}
    
    	// Convert the dividend and divisor to be positive number
    	positiveDividend, positiveDivisor := int(math.Abs(float64(dividend))), int(math.Abs(float64(divisor)))
    
    	for positiveDividend >= positiveDivisor {
    		shift := 0
    		for positiveDividend >= (positiveDivisor << shift) {
    			shift += 1
    		}
    
    		quotient += (1<< (shift - 1))
    		positiveDividend -= (positiveDivisor << (shift - 1))
    	}
    	
    	return int(math.Min(float64(maxInt), math.Max(float64(sign) * float64(quotient), float64(minInt))))
    }
    

    总结

    移位操作虽然好,但也不是唯一解,回忆一下小时候还没学乘法的时候,我们也可以用加法去模拟乘法,所以利用累加来模拟出两数之商更直观。
    经过我的尝试,我发现完全减法会导致超时问题,不得不结合shifting操作,代码如下所示:

    
    func divide(dividend int, divisor int) int {
    	quotient := 0
    	maxInt := math.MaxInt32
    	minInt := math.MinInt32
    	if divisor == 0 || (dividend == minInt && divisor == -1) {
    		return maxInt
    	}
    	// determine the sign of the quotient
    	sign := -1
    	if (dividend ^ divisor) >= 0 {
    		sign = 1
    	}
    
    	// Convert the dividend and divisor to be positive number
    	positiveDividend, positiveDivisor := int(math.Abs(float64(dividend))), int(math.Abs(float64(divisor)))
    
    	// Every time postiveDividend subtract with the value of the divisor
    	for positiveDividend >= positiveDivisor {
    		// Initialize variables for binary search
            tempDivisor := positiveDivisor
            multiple := 1
            
            // Perform binary search-like division
            for positiveDividend >= (tempDivisor << 1) {
                tempDivisor <<= 1
                multiple <<= 1
            }
            
            // Subtract the multiple of divisor from dividend
            positiveDividend -= tempDivisor
            // Add the multiple to quotient
            quotient += multiple
    	}
    	return int(math.Min(float64(maxInt), math.Max(float64(sign) * float64(quotient), float64(minInt))))
     }
    
    
  • 相关阅读:
    Windows cmd命令
    0基础学习VR全景平台篇第142篇:VR直播下载流程
    用“和美”丈量中国丨走进酒博物馆系列⑨
    每日一题-字典
    进程地址空间详解
    【GitLab私有仓库】在Linux上用Gitlab搭建自己的私有库并配置cpolar内网穿透
    pip工具的使用:基本+高级用法
    linux备份mysql8.0数据库脚本
    PyTorch实战-实现神经网络图像分类基础Tensor最全操作详解(一)
    SSD写放大的优化策略要统一标准了吗?
  • 原文地址:https://www.cnblogs.com/freephp/p/18173652