剑指offer(专项突破版)日常刷题 1~3
1.给定两个整数 a 和 b ,求它们的除法的商 a/b ,要求不得使用乘号 ‘*’、除号 ‘/’ 以及求余符号 ‘%’ 。
注意:
整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231−1]。本题中,如果除法结果溢出,则返回 231 − 1
class Solution {
public int divide(int a, int b) {
if (a == Integer.MIN_VALUE && b == -1) {
return Integer.MAX_VALUE;
}
/*
判断是否同号,同号则 结果为正数
*/
boolean flag = false;
if ((a<0 && b<0) || (a>0 && b>0)) {
flag = true;
}
long dividend = Math.abs((long) a);
long divisor = Math.abs((long) b);
if (dividend < divisor) {
return 0;
}
/*
计算 结果的绝对值
*/
int result = 0;
int shift = 31;
while (dividend >= divisor) {
while (dividend < divisor << shift) {
shift--;
}
dividend -= divisor << shift;
result += 1 << shift;
}
return flag ? result : -result;
}
}
2.给定两个 01 字符串 a 和 b ,请计算它们的和,并以二进制字符串的形式输出。
输入为 非空 字符串且只包含数字 1 和 0。
class Solution {
public String addBinary(String a, String b) {
String ans = ""; // 保存最后的结果
int carryBit = 0; // 进位
int curA = a.length() - 1; // 记录当前字符 a 遍历的位置
int curB = b.length() - 1; // 记录当前字符 b 遍历的位置
// 遍历字符串,当两个两个字符串 a,b都遍历完了后就结束循环
while (curA >= 0 || curB >= 0){
int tmp;// 保存 b对应位 + a 对应位 + 进位 的临时结果
if(curA < 0)
tmp = (b.charAt(curB--) - 48 + carryBit);
else if(curB < 0)
tmp = (a.charAt(curA--) - 48 + carryBit);
else{
tmp = a.charAt(curA--) + b.charAt(curB--) - 96 + carryBit;
}
carryBit = tmp / 2; // 更新进位
ans = (tmp % 2) + ans; // 将这一轮的运算的结果加到前面
}
// 当 a 和 b 所有位都遍历完了后,还需要查看是否有进位,如果有进位这需要将进位加上。
if(carryBit == 1) ans = carryBit + ans;
return ans;
}
}
3.给定一个非负整数 n ,请计算 0 到 n 之间的每个数字的二进制表示中 1 的个数,并输出一个数组。
class Solution {
public int[] countBits(int n) {
int[] ans = new int[n + 1];
for(int i = 1; i <= n; i++){
// 如果当前num为偶数,则二进制中1的个数为 num/2 的二进制中1的个数。
if(i % 2 == 0)
ans[i] = ans[i/2];
// 如果当前num为奇数,则二进制中1的个数为前一个数二进制1的个数+1。
else
ans[i] = ans[i-1] + 1;
}
return ans;
}
}