LeetCode-338. Counting Bits
解题思路
- 当然,如果逐位取模再判断是不是
1
来计算1
的个数当然可以,但这样时间复杂度就是O(n*sizeof(integer)) 了,我们想要O(n) 就好。 - 所以,在于对给定的数
num
,我们对区间0 ≤ i ≤ num
中的每个数求1
的个数的时间复杂度都要为O(1)
。 - 要用到位操作来计算:一个
int
为32位,先两两一组相加,之后四个四个一组相加,接着八个八个,最后就得到各位之和了,例如:对于一个8位整数122,用二进制表达是0111 1010
,相加的过程如果:
算法描述
- 这里一个重点难点就是怎样计算每两位,每4位,每8位,每16位,每32位中的
1
的个数,用到了移位和与的操作,看下面的代码实现就清楚了。
代码实现-Go
- Java版-JDK的Integer.bitCount源码:
func countBits(num int) []int {
var arr []int
var temp int
for i := 0; i <= num; i++ {
temp = countB(i)
arr = append(arr,temp)
}
return arr
}
func countB(num int) int {
num = (num & 0x55555555) + ((num >> 1) & 0x55555555)
num = (num & 0x33333333) + ((num >> 2) & 0x33333333)
num = (num & 0x0f0f0f0f) + ((num >> 4) & 0x0f0f0f0f)
num = (num & 0x00ff00ff) + ((num >> 8) & 0x00ff00ff)
num = (num & 0x0000ffff) + ((num >> 16) & 0x0000ffff)
return num
}
运行结果性能数据:
Runtime : 864 ms, faster than 44.19% of Go online submissions for Counting Bits.
Memory Usage : 8.1 MB, less than 100.00% of Go online submissions for Counting Bits.