1.a + b问题
例如:0b01001010 + 0b00110011
0100 1010
0011 0011
首先,计算不需要进位的地方,a ^ b之后:
0111 1101
然后计算需要进位的地方,a & b之后:
0000 0010
接着对需要进位的地方进行进位 <<1:
0000 0100
此时应该计算的值就变成了:
0111 1101
0000 0100
重复上面的步骤,可以得出:0b01111101
因为(a & b) << 1,也就是进位不为0决定了要不要循环,不需要进位直接抑或就行了,所以:
int Add(int num1,int num2) {
if(0 == (num1 & num2)) {
return num1 ^ num2;
}
return Add(num1 ^ num2, (num1 & num2) << 1);
}
2.尾部的零
样例:11! = 39916800,结果为2.
把1 x 2 x 3 x …看成 1 x 2 x3 x4 x 5 x (2 x 3) x…
最后每一个2 x 5都将产生一个0,又因为2的个数总是多于5的个数的,所以其实0的个数就是5的个数,此题便成了找1~11由5组成的数的个数。
long long trailingZeros(long long n) {
long sum = 0;
while (0 != n){
sum += n / 5;
n /= 5;
}
return sum;
}
3.计算数字k在0到n中的出现的次数,k可能是0~9的一个值
输入:
k = 1, n = 12
输出:
5
解释:
在 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] 中,我们发现 1 出现了 5 次 (1, 10, 11, 12)(注意11中有两个1)
方式一:遍历统计
遍历所有的数,计算每个数中查询数出现的次数
int digitCounts(int k, int n) {
int count = 0;
if (k == 0) {
count = 1;
}
for (int i = 1; i <= n; i++) {
int number = i;
while (number > 0) {
if (number % 10 == k) {
count += 1;
}
number /= 10;
}
}
return count;
}
方式二:按位统计
主要原理:每10个数,必定出现一次查询数,所以直接统计每位出现查询数的次数,比如:
k = 3, n = 2544
在个位上:出现254 + 1次,1是个位数字4单独处理2543
在十位上:出现25 + 1次,1是十位数字4单独处理253x
在百位上:出现2 + 1次,…
int digitCounts(int k, int n) {
int count = 0 , x;
if (k == 0 && n == 0) count = 1;
for (int i = 1;x = n / i;i *= 10) {
int high = x / 10;
if (k == 0) {
if (high) high--;
else {
count++;
break;
}
}
count += high * i;
int current = x % 10;
if (current > k) count += i;
else if (current == k) count += n - x * i + 1;
}
return count;
}