九日集训(第一天)函数
三、课后习题
课后所有习题,在上文都能找到答案,请务必刷掉 五道 以上,然后在【九日集训】打卡区进行打卡。只有第一天坚持下来,才会有第二天。 坚持!加油!你可以的!
不用加号的加法,劝大家第一天做题的时候,不要去想位运算的解法,就乖乖的返回 a + b 就好了,等九日集训结束,回顾的时候再来看解题报告:不用加号的加法解题报告。
课后习题中有两道题处理不来。
两数相除
在处理整数除法时没有考虑到整数溢出的情况。
原来的代码
class Solution {
public:
int divide(int dividend, int divisor) {
long long ret = (long long)dividend / (long long)divisor;
return ret;
}
};
当 dividend 为 INT_MIN(即 -2147483648)且 divisor 为 -1 时,按照数学上的除法规则,结果应该是 2147483648。然而,这个数值超出了 int 类型的最大值 INT_MAX(即 2147483647),因此按照C++标准,这时会发生溢出。
在C++中,当有符号整数溢出时,结果是未定义的(Undefined Behavior),这意味着你不能依赖任何特定的行为。然而,许多编译器(包括常见的 GCC 和 Clang)在发生溢出时会回绕(wrap around),即结果会变成相反数的最大值 INT_MIN。因此得到了 -2147483648 而不是期望的 2147483647。
为了解决这个问题,需要手动处理溢出的情况。可以在除法执行前检查是否会发生溢出,如果会发生溢出,直接返回 INT_MAX。
class Solution {
public:
int divide(int dividend, int divisor) {
// 处理溢出的特殊情况
if (dividend == INT_MIN && divisor == -1) {
return INT_MAX;
}
// 使用 long long 类型防止在计算过程中溢出
long long ret = (long long)dividend / (long long)divisor;
return ret;
}
};
反转两次的数字
非负整数进行两次反转操作不变的充要条件即为:该整数为 0 或该整数结尾不含 0。而后者等价于该数模 10 的余数不为 0。我们按照该条件判断并相应返回结果即可。
class Solution {
public:
bool isSameAfterReversals(int num) {
return num == 0 || num % 10 != 0;
}
};