位运算面试题总结

来源:互联网 发布:阿里云服务器个人 编辑:程序博客网 时间:2024/05/17 07:11

更新二进制位

题目链接http://www.lintcode.com/zh-cn/problem/update-bits/

题目描述

给出两个32位的整数N和M,以及两个二进制位的位置i和j。写一个方法来使得N中的第i到j位等于M(M会是N中从第i为开始到第j位的子串)

样例

N = (10000000000)2,M =     (10101)2, i = 2, j = 6返回N = (10001010100)2
class Solution {public:    /**     *@param n, m: Two integer     *@param i, j: Two bit positions     *return: An integer     */    int updateBits(int n, int m, int i, int j) {        // write your code here,位数从0开始.        unsigned int mask;        /*        如果j<31,将i到j位清0,利用((1<<(j+1))-(1<<i))得到i~j之间全是1的数,再取反;        如果j=32,i~最高位全部清0,(1<<i)-1可得到i~最高位之间全是0,其他位为0的数;        */        if(j < 31) {            //方法1            //mask = ~((1 << (j+1)) - (1 << i));            //方法2            mask = ~((((0xFFFFFFFF) << (31 - j)) >> (31 - j + i)) << i);        }        else            mask = (1 << i) - 1;        return (m << i) + (n & mask);    }};

 A + B问题

题目链接http://www.lintcode.com/zh-cn/problem/a-b-problem/

题目描述:给出两个整数a和b, 求他们的和, 但不能使用 + 等数学运算符。

主要利用异或运算来完成
异或运算有一个别名叫做:不进位加法,那么a ^ b就是a和b相加之后,该进位的地方不进位的结果,然后下面考虑哪些地方要进位,自然是a和b里都是1的地方,a & b就是a和b里都是1的那些位置,a & b << 1 就是进位之后的结果。所以:a + b = (a ^ b) + (a & b << 1),令a’ = a ^ b, b’ = (a & b) << 1,可以知道,这个过程是在模拟加法的运算过程,进位不可能一直持续,所以b最终会变为0。

class Solution {public:    /*     * @param a: The first integer     * @param b: The second integer     * @return: The sum of a and b     */    int aplusb(int a, int b) {        // write your code here, try to do it without arithmetic operators.        while (b != 0) {            int c = a & b;            a = a ^ b;            b = c << 1;            //cout<<a<<b<<endl;        }        return a;    }};

检验整数n是不是2的幂数

题目链接http://www.lintcode.com/zh-cn/problem/o1-check-power-of-2/

如果n是2的幂数

  1. n > 0
  2. n的二进制数中只有一个1
class Solution {public:    /*     * @param n: An integer     * @return: True or false     */    bool checkPowerOf2(int n) {        // write your code here,考虑特殊情况0和最小负数        return n > 0 && ((n & (n - 1)) == 0);    }};

计算在一个 32 位的整数的二进制表式中有多少个 1

题目链接http://www.lintcode.com/zh-cn/problem/count-1-in-binary/

由x & (x - 1)消去x最后一位的1可知。不断使用 x & (x - 1) 消去x最后一位的1,计算总共消去了多少次即可。

class Solution {public:    /**     * @param num: an integer     * @return: an integer, the number of ones in num     */    int countOnes(int num) {        // write your code here        unsigned int n = (unsigned int)num;        int times = 0;        while(n)        {            n = n & (n - 1);            times++;        }        return times;    }};

如果要将整数A转换为B,需要改变多少个bit位?

题目链接http://www.lintcode.com/zh-cn/problem/flip-bits/

可以转化为A^B中1的个数

class Solution {public:    /**     *@param a, b: Two integer     *return: An integer     */    int bitSwapRequired(int a, int b) {        // write your code here        int c = a ^ b;        int ret = 0;        while (c) {            ret += 1;            //cout<<c<<endl;            c = c & (c - 1);        }        return ret;    }};

数组中,只有一个数出现一次,剩下都出现两次,找出出现一次的数

题目链接http://www.lintcode.com/en/problem/single-number/

利用 a ^ b ^ b = a

class Solution {public:    /**     * @param A: Array of integers.     * return: The single number.     */    int singleNumber(vector<int> &A) {        // write your code here        int size = A.size();        if (size == 0) {            return 0;        }        int ret = A[0];        for (int i = 1; i< size; i++)        {            ret = ret ^ A[i];        }        return ret;    }};

数组中,只有一个数出现一次,剩下都出现三次,找出出现一次的数

题目链接http://www.lintcode.com/zh-cn/problem/single-number-ii/

class Solution {public:    /**     * @param A : An integer array     * @return : An integer     */    int singleNumberII(vector<int> &A) {        // write your code here        int size = A.size();        int times[32] = {0};//统计每一位中1的个数        for (int i = 0; i < size; i++) {            for (int j = 0; j < 32; j++) {                if ((A[i] & (1 << j)) > 0) {                    times[j] += 1;                    times[j] %= 3;//防止越界                }            }        }        int ret = 0;        for (int i = 31; i >= 0; i--) {            ret = ret << 1;            ret += times[i];        }        return ret;    }};

数组中,只有两个数出现一次,剩下都出现两次,找出出现一次的数

题目链接http://www.lintcode.com/zh-cn/problem/single-number-iii/

求二进制中最后一位1的个数

原码,二进制表示

反码,正数的反码就是原码,负数的反码是符号位不变,其余位取反

补码,正数的补码就是原码,负数的补码是反码 + 1

在计算机中都是采用补码的形式存储

所以,a&-a就是a最后一位1的位置

不妨假设出现一个的两个元素是x,y,那么最终所有的元素异或的结果就是res = x^y。并且res!=0,那么我们可以找出res二进制表示中的某一位是1。对于原来的数组,我们可以根据这个位置是不是1就可以将数组分成两个部分。x,y在不同的两个子数组中。而且对于其他成对出现的元素,要么在x所在的那个数组,要么在y所在的那个数组。

class Solution {public:    /**     * @param A : An integer array     * @return : Two integers     */    vector<int> singleNumberIII(vector<int> &A) {        // write your code here        int size = A.size();        vector<int> ret = {0,0};        if (size == 0) {            return ret;        }        int diff = A[0];        for (int i = 1; i < size; i++) {            diff ^= A[i];        }        diff &= -diff;        for (int i = 0; i < size; i++) {            if ((A[i] & diff) == 0) {                ret[0] ^= A[i];            }            else {                ret[1] ^= A[i];            }        }        return ret;    }};

%3

给一个很长的二进制字符串,计算除以3的余数

奇数位除以3余1,偶数位除以3余2,所以

  1. 奇数位1的个数等于偶数位1的个数,则余数为0
  2. 奇数位个数大于偶数位,个数相减后 %3
  3. 偶数位个数大于奇数位,个数相减后*2%3
int fun(char* s, int len) {    if (s == NULL)        return 0;    int odd_num = 0;    int  even_num = 0;    int times = 1;    for(int i = len - 1; i>=0; i--) {        if(s[i] == '1') {             if(times & 1)                odd_num++;            else                even_num++;        }        times++;    }    if(odd_num > even_num)        return (odd_num-even_num)%3;    else        return (odd_num - even_num) * 2 % 3;}int main(){    char a[] = "10010001101000101011001111000";    cout <<fun(a,sizeof(a) - 1);}
0 0
原创粉丝点击