leetcode 338. Counting Bits

本文探讨了如何高效计算一个非负整数范围内每个数的二进制表示中1的数量。提供了一种线性时间复杂度O(n)的解决方案,并通过实例展示了不同方法的实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1's in their binary representation and return them as an array.

Example:
For num = 5 you should return [0,1,1,2,1,2].

Follow up:

  • It is very easy to come up with a solution with run time O(n*sizeof(integer)). But can you do it in linear time O(n) /possibly in a single pass?
  • Space complexity should be O(n).
  • Can you do it like a boss? Do it without using any builtin function like __builtin_popcount in c++ or in any other language.
这个我用的方法就是按照传统人的思路来看1的个数的方法,+1的话,指针从最右开始,如果为0,变成1;如果为1,指针前移到为0的为止,变成1,再将之后的归0,指针再回到最右。但是这个方法时间复杂度不是很可观。

public class Counting_Bits_338 {

	public int[] countBits(int num) {
		int[] a = new int[32];
		int pointer = 0;
		int[] result = new int[num + 1];
		int count = 0;
		for (int i = 1; i <= num; i++) {
			if (a[pointer] == 0) {
				a[pointer] = 1;
				count++;
			} else {
				while(a[pointer]==1){
					pointer++;
				}
				a[pointer] = 1;
				count++;
				pointer--;
				while(pointer>=0){
					a[pointer] = 0;
					count--;
					pointer--;
				}						
				pointer = 0;
			}
			result[i] = count;
		}
		return result;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Counting_Bits_338 c = new Counting_Bits_338();
		System.out.println(Arrays.toString(c.countBits(7)));
	}

}
大神的方法,大神发现了规律: f[i] = f[i / 2] + i % 2.
public int[] countBits(int num) {
    int[] f = new int[num + 1];
    for (int i=1; i<=num; i++) f[i] = f[i >> 1] + (i & 1);
    return f;
}
三行解决真是太漂亮了,数学拯救人类!

还有其他的规律:

This uses the hint from the description about using ranges. Basically, the numbers in one range are equal to 1 plus all of the numbers in the ranges before it. If you write out the binary numbers, you can see that numbers 8-15 have the same pattern as 0-7 but with a 1 at the front.
My logic was to copy the previous values (starting at 0) until a power of 2 was hit (new range), at which point we just reset the t pointer back to 0 to begin the new range.


这样一看真的:[2,3]是[0,1]对应数字+1;[4,5,6,7]是[0,1,2,3]对应数字+1;[8,9,10,....,15]是[0,1,2,...,7]对应数字+1;我图片中的算法对于每个数字还要算出它的count(小于等于它的最大2指数),时间复杂度也不好,大神给出了两个指针一次遍历的算法:

public int[] countBits(int num) {
    int[] ret = new int[num+1];
    ret[0] = 0;
    int pow = 1;
    for(int i = 1, t = 0; i <= num; i++, t++) {
        if(i == pow) {
            pow *= 2;
            t = 0;
        }
        ret[i] = ret[t] + 1;
    }
    return ret;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值