338.Counting Bits---位运算---《剑指offer》32
题目链接:https://leetcode.com/problems/counting-bits/description/
题目大意:求解从0到num的所有数的二进制表示中所有1的个数。
法一:暴力解,两个for循环,分别求解每一个二进制表示,然后计数其中1的个数。代码如下(耗时9ms):
1 public int[] countBits(int num) { 2 int[] res = new int[num+1]; 3 for(int i = 0; i <= num; i++) { 4 res[i] = bit(i); 5 } 6 return res; 7 } 8 public static int bit(int num) {//转换为二进制计数1的个数 9 int cnt = 0; 10 while(num != 0) { 11 cnt += num % 2; 12 num /= 2; 13 } 14 return cnt; 15 }
法二:在法一的基础上,优化了内层循环,利用记忆搜索的思想,因为已经用res数组存下了i之前数据的1的个数,而当i/2之后得到的数据,一定是之前已经计算过的数据,这样就可以直接拿过来用,而不用再次计算。比如要计算5时,只需要算出5%2得到的数值,然后就要对5进行/2运算了,而5/2=2,在前面已经存储过res[2]的数值了,所以就得到res[5]=5%2+res[5/2]。代码如下(耗时3ms):
1 public int[] countBits(int num) { 2 int[] res = new int[num+1]; 3 res[0] = 0; 4 for(int i = 1; i <= num; i++) { 5 int tmp = i; 6 res[i] = (tmp % 2) + res[tmp / 2]; 7 } 8 return res; 9 }
法三:在法二的基础上,用位运算的办法来做取余和除2运算。的确快了点。代码如下(耗时2ms):
1 public int[] countBits(int num) { 2 int[] res = new int[num + 1]; 3 res[0] = 0; 4 for(int i = 1; i <= num; i++) { 5 res[i] = (i & 1) + res[i >> 1]; 6 } 7 return res; 8 }