位运算各种操作

1.二进制中1的数

2.数组中只出现一次的数字

3.不用加减乘除做加法

4.不用额外变量交换两个整数的值

5.不用比较判断找出两个数中较大的数

6.在数组中找到出现奇数次的数

 

1. 请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如把9表示成二进制是1001,有2位是1.因此如果输入9,该函数输出2。
       为了避免死循环,可以不右移输入的数字n。首先把n和1做与运算,判断n的最低位是不是1.接着把1左移一位得到2,再和n做与运算,就能判断n的次低位是不是1.....这样反复左移,每次都能判断n的其中一位是不是1。

//一般解法
int  NumberOf1(int n)
{
    int count = 0;
    unsigned int flag = 1;
    while (flag){
        if (n & flag) count++;
        flag = flag <<1;
    }
    return count;
}

//好的解法:
int NumberOf1(int n)
{
    int count = 0;
    while (n){
        ++count;
        n=(n-1) & n;
    }
    return count;
}

2.一个整型数组里除了两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1);

unsigned int FindFirstBitIs1(int num)
{
    int indexBit = 0;
    while ((num & 1) == 0 && (indexBit < 8 * sizeof(int))) {
        num = num >> 1;
        ++indexBit;
    }
    return indexBit;
}

bool IsBit1(int num, unsigned int indexBit)
{
    num = num >> indexBit;
    return (num & 1);
}

void FindNumsAppearOnce(int data[], int length, int *num1, int *num2)
{
    if (data == NULL || length < 2)return;
    int resultExclusiveOR = 0;
    for (int i = 0; i < length; ++i)
        resultExclusiveOR ^= data[i];
    unsigned int indexOf1 = FindFirstBitIs1(resultExclusiveOR);
    *num1 = *num2 = 0;
    for (int j = 0; j < length; ++j) {
        if (IsBit1(data[j], indexOf1))
            *num1 ^= data[j];
        else
            *num2 ^= data[j];
    }
}

3.写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。

int Add(int num1,int num2)
{
    int sum,carry;
    do {
        sum = num1^num2;
        carry = (num1 & num2) << 1;
        num1 = sum;
        num2 = carry;
    } while (num2 != 0);
    return num1;
}

4. 如何不用额外的变量交换两个整数的值?

a=a^b;
b=a^b;
a=a^b;

5. 给定两个32位整数a和b,返回a和b中较大的(要求不用任何比较判断)。

int flip(int n) {//n为1返回0,n为0返回1
    return n ^ 1;
}

int sign(int n) {//n为非负数返回1,n为负数返回0
    return flip((n>>31)&1);
}

int getMaxNumber(int a, int b)
{
    int c = a - b;
    int sa,sb,sc;
    sa = sign(a), sb = sign(b), sc = sign(c);
    int diffSab = sa^sb;
    int sameSab = flip(diffSab);
    int resa = diffSab*sa + sameSab*sc;
    int resb = flip(resa);
    return a*resa + b*resb;
}


6. 给定一个整型数组arr,其中只有一个数出现了奇数次,其他的数都出现了偶数次,打印这个数。
    进阶:有两个数出现了奇数次,其他的数都出现了偶数次,打印这两个数。

void findOdd1(vector<int>a)
{
    int res = 0;
    for (int i = 0; i < a.size(); i++) {
        res ^=a[i];
    }
    cout << res<< endl;
}

void findOdd2(vector<int>a)
{
    int res = 0, hasOne = 0;
    for (int i = 0; i < a.size(); i++) {
        res ^= a[i];
    }
    int rightOne = res & (~res+1);
    for (int i = 0; i < a.size(); i++) {
        if ((a[i] & rightOne) != 0)
            hasOne ^= a[i];
    }
    cout <<hasOne<<" "<<(res^hasOne) << endl;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值