一、整数基础知识
1、整数是一种基本数据类型
-
一共包括四种不同的整数类型,分别是:byte(1字节=8位),short(2字节),int(4字节),long(8字节)
-
扩展,其他的基本数据类型, 浮点型(float,double),布尔型(bool),字符型(char),string不是基本数据类型,他是字符数组类型
2、整数数值表示范围
-
int类型表示的数值范围为(-2^31~2^31-1),也就是(-2147483648 - 2147483647)
-
使用二进制表示,最高位为0则为正数,最高位为1为负数
3、正数运算遵循四则运算
- 如果超出数值范围会产生溢出,不会报错,但最终结果不正确
二、LeetCode29 两数相除
1、题目信息:
cpp
给你两个整数,被除数 dividend 和除数 divisor。将两数相除,要求 不使用 乘法、除法和取余运算。
整数除法应该向零截断,也就是截去(truncate)其小数部分。例如,8.345 将被截断为 8 ,-2.7335 将被截断至 -2 。
返回被除数 dividend 除以除数 divisor 得到的 商 。
注意:假设我们的环境只能存储 32 位 有符号整数,其数值范围是 [−231, 231 − 1] 。本题中,如果商 严格大于 231 − 1 ,则返回 231 − 1 ;如果商 严格小于 -231 ,则返回 -231 。
示例 1:
输入: dividend = 10, divisor = 3
输出: 3
解释: 10/3 = 3.33333.. ,向零截断后得到 3 。
示例 2:
输入: dividend = 7, divisor = -3
输出: -2
解释: 7/-3 = -2.33333.. ,向零截断后得到 -2 。
提示:
-231 <= dividend, divisor <= 231 - 1
divisor != 0
2、解题思路:
-
输入两个整数,分别是被除数dividend和除数divisor,现在要求不适用乘号,除号和取余运算符,来求两个数相除的结果。那可以选择使用加法、减法和位移运算符来实现。
-
题目提到了使用int整数类型,可能会导致数值溢出,为解决这个问题,可对int类型进行类型转换为long。两个数都转换成正整数,至于他们相处的最终正负号使用一个变量sign来表示。
3、暴力解法:
-
要求被除数与除数的商,可以先将两个数都转换成正整数,采用减法的方式来处理,使用while循环,判断条件为只要被除数比除数值大,则被除数的值就每次减少除数的大小,并计算while循环减去的次数,直到被除数的值小于除数。此时while循环中减去的次数就接近结果值。
-
说接近结果值,还有一个是要考虑商的正负数处理。
4、画图理解:

5、代码实现:
cpp
int divide(int dividend, int divisor)
{
long res = 0;
int sign = 1; // 计算符号
// 获取他的绝对值,先转成longlong类型,再转换符号
long dividendL = dividend;
long divisorL = divisor;
// 获取绝对值
if (dividend < 0)
{
dividendL = -dividendL;
}
if (divisor < 0)
{
divisorL = -divisorL;
}
// 获取正负数符号
if ((dividend < 0 && divisor < 0) || (dividend >= 0 && divisor > 0))
{
sign = 1;
}
else
{
sign = -1;
}
while (dividendL >= divisorL)
{
dividendL -= divisorL;
res++;
}
if (sign < 0)
{
res = -res;
}
if (res > INT32_MAX)
{
return INT32_MAX;
}
if (res < INT32_MIN)
{
return INT32_MIN;
}
return res;
}
三、折半解法:
1、解题思路:
-
上面的暴力解法使用一层while循环,每次被除数减少除数的大小,他的时间复杂度为O(n)
-
可以通过两层while循环,每次减少数据是除数的倍数,而且这个除数的倍数的结果值,要是小于被除数一半的最大值,而要计算确定除数的倍数值,可使用内层while循环来计算
-
因为不能使用乘法,改为使用整数的移位操作,对除数不断左移<<,在内层while循环中对除数左移一位,他的倍数是2的n次方,直到倍数值大于被除数的一半为止。
-
这样在外层while循环中,就可以一次性减去内层while循环计算得到的除数的倍数值。直到被除数小于除数值,这个倍数值不断累加就是最终结果值。
2、画图理解:

3、代码实现:
cpp
int divide(int dividend, int divisor)
{
long res = 0;
int sign = 1; // 计算符号
// 获取他的绝对值,先转成longlong类型,再转换符号
long dividendL = dividend;
long divisorL = divisor;
// 获取绝对值
if (dividend < 0)
{
dividendL = -dividendL;
}
if (divisor < 0)
{
divisorL = -divisorL;
}
// 获取正负数符号
if ((dividend < 0 && divisor < 0) || (dividend >= 0 && divisor > 0))
{
sign = 1;
}
else
{
sign = -1;
}
// 使用阶乘方式来处理
long temp = 0;
long multi = 0; // 重复的阶乘个数
while (dividendL >= divisorL)
{
multi = 1;
temp = divisorL;
while (dividendL > (temp << 1))
{
multi = multi << 1; // 往左移动
temp = temp << 1;
}
dividendL -= temp;
res += multi;
}
if (sign < 0)
{
res = -res;
}
if (res > INT32_MAX)
{
return INT32_MAX;
}
if (res < INT32_MIN)
{
return INT32_MIN;
}
return res;
}
四、总结:
-
整数包括始终数据类型,他有正负号与数值表示范围
-
整数遵循四则运算法则,超过数值范围会导致数值溢出
-
暴力解法采用被除数不断减去除数的次数,直到被除数小于除数
-
折半解法采用两层while循环,每次减少被除数的一半,采用位移方式减出除数的2的倍数