acwing-801. 二进制中1的个数

给定一个长度为 n 的数列,请你求出数列中每个数的二进制表示中 1 的个数。

输入格式

第一行包含整数 n。
第二行包含 n 个整数,表示整个数列。

输出格式

共一行,包含 n 个整数,其中的第 i 个数表示数列中的第 i 个数的二进制表示中 1 的个数。

数据范围

1≤n≤100000,
0≤数列中元素的值≤10^9

输入样例:

5
1 2 3 4 5

输出样例:

1 1 2 1 2

方法一(暴力):

逐位和 1 进行与运算

#include <bits/stdc++.h>

using namespace std;

unsigned long long n, t;

int getb(unsigned long long num) {
    int res = 0;
    while (num) {
        res += num & 1;
        num >>= 1;
    }
}

int main() {
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> t;
        cout << getb(t) << " ";
    }
}

方法二:

利用计算机以补码存储数字的特点(unsigned没有补码一说,但是转换规则和补码相同,也是取反+1,所以就算上面没有用unsigned,算法不用改动),在补码表示法下:

  1. 一个数算数取反 = 其反码 + 1
  2. 一个数本身与其算数取反只有最后一个 1 是相同的,其它位全部取反,例如12的八位二进制0000 1100,-12则是1111 0100

利用性质2,可以通过 x & (-x)直接得到数字二进制下的最后一位 1,相比暴力法,若二进制存在很多0,那将大大节省时间

#include <bits/stdc++.h>

using namespace std;

unsigned long long n, t;

int main() {
    cin >> n;
    while (n--) {
        cin >> t;
        int res = 0;
        while (t) {
            t -= t & (-t);
            res++;
        }
        cout << res << " ";
    }
}
上一篇:剑指 Offer 42. 连续子数组的最大和


下一篇:大题解析(二)