1.1 整数的基础
...大约 2 分钟
整数分为:
- 无符号数:所有位用于表示数字
 - 有符号数:最高位表示符号,1(负)0(正)
 
n 位二进制表示的整数范围:
- 无符号:[0, ]
 - 有符号: [, ],整数在计算机中采用补码表示
 
1.1.1 问题
输入2个int型整数,进行除法运算后返回商。不得使用乘号(‘*‘),除号(‘/’)和求余符号(‘%’)。溢出时返回整数最大值。假设除数不为0。
例:输入15和2,输出15/2,结果为7
1.1.2 分析
流程
可基于减法来进行除法运算,使用被除数减去除数后,将结果与除数比较,若大于则继续,否则商就是计算结果(实际上为除法的计算原理)。

但是上述流程,当除数为1时,时间复杂度达到O(n),故需进行优化。
优化
在判断被除数大于除数时,可进一步判断是否大于其2倍,4倍...乃至2^k倍。即满足(b为被除数):
之后再按减法流程进行,此时时间复杂度为O(logn)。

符号
商的符号取决于被除数和除数,所以结果的正负在计算之前即可得出。
计算时,若将其全部转为正数计算,当数字为最小负整数时,转换成正数会导致溢出(有符号整数范围 [, ],无法表示)
所以计算时需要将其全部转换成负数计算。
边界
由于除数不为0,所以溢出的情况只有一种,即 ,此时结果将超出最大的整数范围。
1.1.3 题解
根据上述的分析可得出流程:

package soint
import (
	"math"
)
func divide(dividend, divisor int32) int32 {
	if dividend == math.MinInt32 && divisor == -1 {
		return math.MaxInt32
	}
	negative := 2
	if dividend > 0 {
		negative--
		dividend = -dividend
	}
	if divisor > 0 {
		negative--
		divisor = -divisor
	}
	result := divideCore(dividend, divisor)
	if negative == 1 {
		return -result
	}
	return result
}
func divideCore(dividend, divisor int32) int32 {
	var quotient int32
	quotient = 0
	for dividend <= divisor {
		u := divisor
		var v int32 = 1
		for divisor >= (math.MinInt32>>1) && dividend <= u+u {
			u += u
			v += v
		}
		quotient += v
		dividend -= u
	}
	return quotient
}
Reference
 Powered by  Waline  v2.15.2
