经过一年的雁栖学习,终于回到了实验室,开始了研二的科研生活,是时候把我这一年的所学所想所思记录下来,以后我会慢慢更博,争取把以前和以后的学习生活记录下来!
昨天正式”刷”了第一道leetcode,以前总是断断续续地随意翻着做。
题意: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.(给定一个num,输出0到num这num+1个数中每个数有多少位(二进制位)是1,以数组形式返回)
例如: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的个数的题目,《编程之美》2.1节中也有介绍,下面就详细地总结一下:
一.直接法(移位):大家第一反应就是移位+计数,时间复杂度O(logV)(log代表以2为底,V是二进制数的位数)
二.快速法:直接法的时间复杂度依然不是最低,快速法可达到O(m)(m为二进制数中“1”的位数),如何才能直接计算出一个数中位1的个数?
考虑n & (n-1),若n中有m位为1,则 n = n & (n-1)会在循环m次之后,n=0.
eg: n=7
第一次循环:n = 7 (0111),7 (0111)& 6 (0110)= 6(0110)
第二次循环:n = 6(0110), 6(0110)& 5(0101)=4(0100)
第三次循环:n = 4(0100), 4(0100)& 3(0011)=0(0000)
此时,n已经等于0了,n=7中有3位是“1”,所以在循环3次后 n边为0。
《编程之美》中还介绍了另外两种算法,但那两种方法与数字的位数有关,个人认为不通用,便没有介绍。详细见《编程之美》2.1
该leetcode的解法如下,我用java写的,不过语言不重要了,关键是思想!!!!!以后我再做第二遍的时候会考虑用c++或python写,到时候再附加其他语言的代码:
public class Solution {
public int[] countBits(int num) {
int[] result = new int[num+1]; //因为还有0这个数字
for(int i=0;i<=num;i++){
int tmp = 0;
int j=i;
while(j != 0){
j = j&(j-1);
tmp++;
}
result[i] = tmp;
}
return result;
}
}