剑指offer:位运算

JZ64 求1+2+3+…+n
中等 通过率:43.41% 时间限制:1秒 空间限制:64M
知识点基础数学
描述
求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

数据范围: 0 进阶: 空间复杂度 O(1) ,时间复杂度 O(n)
示例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;
    }
};

你可能感兴趣的:(数据结构和算法,算法,位运算)