蓝桥杯《算法很美》第一章 位运算的奇巧淫技学习笔记C/C++【二】

这篇笔记主要讲&运算的巧用。

原理:0作&消除,1作&保留。

《二进制中1的个数》

蓝桥杯《算法很美》第一章 位运算的奇巧淫技学习笔记C/C++【二】_第1张图片

方法一:将1移动到想要判断的那一位上,进行与&操作,&的特点是1&任何数运算均为那个数本身,0&任何数都是0。

/*二进制中1的个数*/
#include 
#include 
#include 
#include 
#include 
using namespace std;
int main() {
    int N,Count=0;
    cin >> N;
    int temp = N;
    int i;
    bool binary[32];
    /*十进制转二进制*/
    for(i=31; i>=0; i--){
        binary[i] = temp%2;
        temp = temp >> 1;
    }
    /*逐位输出二进制形式,并进行比对*/
    for(i=0; i<32; i++){
        cout << binary[i];
        if( (N&(1<

方法二:每次将N右移一位,所以只需判断最后一位是否为1即可。

/*二进制中1的个数*/
#include 
#include 
#include 
#include 
#include 
using namespace std;
int main() {
    unsigned N,Count=0;
    cin >> N;
    int temp = N;
    int i;
    bool binary[32];
    /*十进制转二进制*/
    for(i=31; i>=0; i--){
        binary[i] = temp%2;
        temp = temp >> 1;
    }
    /*逐位输出二进制形式,并判断每一位是否为1*/
    for(i=0; i<32; i++){
        cout << binary[i];
        if( ((N>>i)&1) == 1 )
            Count ++;
    }
    cout << endl;
    cout << Count << endl;
    return 0;
}

个人认为这个最好想,需要注意的是移位要使用逻辑运算。

方法三:每次消除一个1,减1的效果是将最低一位的1变为0,这一位后面的所有位的0都变为1,用-1后的数与原数&,就消掉了最末尾的1,以此类推,结束条件为最终结果是0,这种方法效率最高。

/*二进制中1的个数*/
#include 
#include 
#include 
#include 
#include 
using namespace std;
int main() {
    unsigned N,Count=0;
    cin >> N;
    int temp = N;
    int i;
    bool binary[32];
    /*十进制转二进制*/
    for(i=31; i>=0; i--){
        binary[i] = temp%2;
        temp = temp >> 1;
    }
    /*每次对N减1再与原来的N做&操作即可将最靠后的1变为0,直到所有的1都变为0则停止计数*/
    while(N != 0){
        N=(N - 1) & N;
        Count ++;
    }
    cout << endl;
    cout << Count << endl;
    return 0;
}

《是不是2的整数次方》

转化为二进制问题:是否只有一个1,例如001000,0100000等,这种数就是2的整次方数,聪明如你,已经看出利用上面的第三种方法的原理就可以解决这个问题。(不考虑负整数次方)

/*判断一个数是否是2的倍数*/
#include 
#include 
#include 
#include 
#include 
using namespace std;
int main() {
    unsigned N;
    cin >> N;
    /*仅适用一条if-else语句*/
    if(N&(N-1))
        cout << "No" << endl;
    else
        cout << "Yes" << endl;
    return 0;
}

《将整数的奇偶位互换》

比如1001,第0位与第1位互换,第2位与第3位互换......结果为0110

思路:利用了&和^的结合,上一篇笔记讲过^的作用是:0作^保留,1作^取反。可以借助辅助空间,将十进制先转化为二进制,再令奇偶位互换。当然这章主要是利用位运算,那么就一定有简单的方法,主要思路是先保留奇数位再保留偶数位,通过移位再异或,将奇偶位互换。

/*将整数的奇偶位互换*/
#include 
#include 
#include 
#include 
#include 
using namespace std;
int main() {
    unsigned N;
    cin >> N;
    unsigned ou = N&0xaaaaaaaa;/*1010...1010 消去偶数位,所有偶数位都为0*/
    unsigned ji = N&0x55555555;/*0101...0101 消去奇数位,所有奇数位都为0*/
    cout << ((ou>>1)^(ji<<1)) << endl;/*偶数位右移,奇数位左移,顺序就刚好和之前相反*/
    return 0;
}

 

你可能感兴趣的:(算法)