0
点赞
收藏
分享

微信扫一扫

位 运 算

phpworkerman 2022-02-20 阅读 54

 二进制中1的个数

算法1、(暴力枚举) O(nlongn)

思路:

对于每个数字a,a&1得到了该数字的最后一位,之后将a右移一位,直到位0,就得到了1的个数

C++ 代码

#include<iostream>
using namespace std;
int n;
int a,k;
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&a);
        k=0;
        while(a){
            k+=a&1;
            a=a>>1;
        }
        printf("%d ",k);
    }
    return 0;
}

算法2、 (lowbit) O(nlogn)

思路:

使用lowbit操作,进行,每次lowbit操作截取一个数字最后一个1后面的所有位,每次减去lowbit得到的数字,直到数字减到0,就得到了最终1的个数;

根据计算机负数表示的特点,数字在内存中以补码形式存储,正数原码、反码、补码相同;负数表示形势是补码,就是反码+1,

如:10的补码00001010,-10的补码为反码+1,即11110110(11110101+1),二者按位与得到了00000010,就是2,10 - 2=8,8补码00001000.......一直减下去直到变成00000000

#include<iostream>
using namespace std;
int lowbit(int x){
    return x&(-x);
}
int main(){
    int n;
    cin>>n;
    while(n--){
        int x;
        cin>>x;

        int res=0;
        while(x) x-=lowbit(x),res++;

        cout<<res<<' ';
    }
    return 0;
}

算法3、(位运算) 接近O(1)

思路:

读懂了算法2的操作就明白了,算法2的优化

#include <iostream>
using namespace std;

int cnt(int b){
 int res = 0;
 while (b>0) {
    b = b & (b-1);
    res++;
 }
 return res;
}


int main(){
int n, b;
cin >> n;
for (int i=0;i<n;i++) {
    cin >> b;
    cout << cnt(b)<<" ";
}

return 0;
}
举报

相关推荐

0 条评论