JZ64 求1+2+3+…+n
中等 通过率:43.41% 时间限制:1秒 空间限制:64M
知识点基础数学
描述
求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
数据范围: 0
示例1
输入:
5
返回值:
15
示例2
输入:
1
返回值:
1
//短路求值
class Solution {
public:
int Sum_Solution(int n) {
n && (n += Sum_Solution(n - 1));
return n;
}
};
另一道题:
同样的限制条件,怎么使得两数之积总是小于等于255。
即两个数a和b,如果ab大于255,便返回255,否则返回ab。
int multi(inta, int b)
{
int result;
(result = (a*b)) > 255 && (result = 255);
return result;
}
JZ15 二进制中1的个数
简单 通过率:35.79% 时间限制:1秒 空间限制:256M
知识点基础数学
描述
输入一个整数 n ,输出该数32位二进制表示中1的个数。其中负数用补码表示。
数据范围:−231<=n<=231−1
即范围为:−2147483648<=n<=2147483647
示例1
输入:
10
返回值:
2
说明:
十进制中10的32位二进制表示为0000 0000 0000 0000 0000 0000 0000 1010,其中有两个1。
示例2
输入:
-1
返回值:
32
说明:
负数使用补码表示 ,-1的32位二进制表示为1111 1111 1111 1111 1111 1111 1111 1111,其中32个1
关联企业
class Solution {
public:
int NumberOf1(int n) {
int count = 0;
while (n != 0) {
//一个整数和这个整数减去1做与运算,等价于把这个整数最右边一个1变成0
n = n & (n - 1);
count++;
}
return count;
}
};
如果一个整数不为0,那么这个整数至少有一位是1。
如果我们把这个整数减1:
(1)原来处在整数最右边的1就会变为0,
(2)原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。
举个例子:
一个二进制数1100,从右边数起第三位是处于最右边的一个1。
减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,
因此得到的结果是1011
我们发现:减1的结果是把最右边的一个1开始的所有位都取反了。
这个时候如果我们再把原来的整数和减去1之后的结果做与运算,
从原来整数最右边一个1那一位开始所有位都会变成0。如1100&1011=1000
一个整数和这个整数减去1做与运算,等价于把这个整数最右边一个1变成0
那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。
11110000
11100000 1次
11000000 2次
10000000 3次
00000000 4次
JZ65 不用加减乘除做加法
简单 通过率:45.77% 时间限制:1秒 空间限制:64M
知识点基础数学
描述
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
数据范围:两个数都满足 −10≤n≤1000
进阶:空间复杂度 O(1),时间复杂度 O(1)
示例1
输入:
1,2
返回值:
3
示例2
输入:
0,0
返回值:
0
位运算:
(1)与运算 a & b 都为1才为1
(2)或运算 a | b 至少有一个为1才为1
(3)异或运算 a ^ b 不同为1
三步走的方式计算二进制值相加:
5-101
7-111
第一步:各位相加的和,得到010,二进制各位相加相当于各位做异或操作,101^111。
第二步:进位相加的和,得到1010,二进制进位相加相当于各位做与操作,再向左移一位,(101&111)<<1。
第三步:重复上述两步, 各位相加 010^1010=1000,进位相加 (010&1010)<<1 = 100。
继续重复上述两步:各位相加 1000^100 = 1100, 进位相加 (1000&100)<<1 = 0
由于进位相加为0,跳出循环,1100为最终结果。
class Solution {
public:
int Add(int num1, int num2) {
while (num2 != 0) {
int temp = num1 ^ num2;
num2 = (num1 & num2) << 1;
num1 = temp;
}
return num1;
}
};