[LeetCode 338] 比特位计数

比特位计数

LeetCode 338

给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案

O(nlogn) 解法

顺序计算 n 个数二进制表示中的 1 的个数, 对于数字 i, 依次与 \(2^k (2^k \le i)\) 作与操作, 若结果为 1 则计数加 1.

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* countBits(int n, int* returnSize){
	int* result = (int*) malloc(sizeof(int) * (n + 1));
	*returnSize = n + 1;
    memset (result, 0, sizeof(int) * (n+1));

    for (int i = 0; i <= n; i++) {
        for (int k = 1; k <= i; k *= 2) {
            if ((i & k) > 0)
                {
                    result[i] ++;
                }
        }
    }

	return result;
}

O(n) 解法

LeetCode 官方题解 tql

DP - 最高有效位

bits[i] 代表数字 i 二进制表示中的 1 的位数, 对于数字 \(x\), \(y\) 是满足 \(y \le x\) 的最大的 2 的幂, 设 z = x - y, 则

\[\mathbf{bits[x] = bits[z] + 1} \]

如果一个数字 \(x\) 是 2 的幂, 则有 \(x \& (x - 1) = 0\)

function countBits(n: number): number[] {
	var bits: number[] = new Array(n + 1);

	bits[0] = 0;
	var y:number = 1;
	for (let x = 1; x <= n ; x++) {
		if ((x & (x - 1)) == 0) {
			y = x;
		}
		bits[x] = bits[x - y] + 1;
	}

	return bits;
};

DP-最低有效位

对于数字 \(x\)

\[\mathbf{bits[x]} = \begin{cases} \mathbf{bits[x/2]} & \mathbf{x} 是偶数 \\ \mathbf{bits[x/2]} + 1 & \mathbf{x} 是奇数 \end{cases} \]

function countBits(n: number): number[] {
	let bits: number[] = new Array(n + 1);

	bits[0] = 0;
	for (let x: number = 1; x <= n; x++) {
		if (x % 2 == 1) {
			// x 是奇数
			bits[x] = bits[Math.floor(x/2)] + 1;
		} else {
			// x 是偶数
			bits[x] = bits[Math.floor(x/2)];
		}
	}

	return bits;
};

DP-最低设置位

定义整数的二进制位最低的 1 所在位为最低设置位, 令 \(y = x \&(x-1)\), 则 \(y\) 为将 \(x\) 的最低设置位从 1 变为 0 后的数字, 显然有 \(0\le y< x\), bits[x] = bits[y] + 1, 即 bits[x] = bits[x & (x-1)] + 1.

function countBits(n: number): number[] {
	let bits: number[] = new Array(n + 1);
	bits[0] = 0;
	for (let x = 1; x <= n; x++) {
		bits[x] = bits[x & (x - 1)] + 1;
	}
	return bits;
};
posted @ 2022-08-04 18:49  昤昽  阅读(26)  评论(0编辑  收藏  举报