比特位计数的基本实现与优化

一.算法题干

给定一个非负整数num。对于0 ≤ i ≤ num范围中的每个数字i,计算其二进制数中的1的数目并将它们作为数组返回。

二.样例

样例1:
输入:2
输出:[0,1,1]
样例2:
输入:5
输出:[0,1,1,2,1,2]

三.解题思路

我一开始想到的是最正统的解法:遍历[0,num]的所有整数,然后对每个整数都不断进行“模2+除以2”的操作,统计这当中模2后得到1的数量(其实也就是转化为二进制后1的个数),最后输出各个小结果组成的vector。

四.实现代码

vector<int> countBits(int n) {
	vector<int> resv;
	for(int i=0;i<=n;++i)
	{
		int t=i,res=0;
		while(t)
		{
			if(t%2) ++res;
			t/=2;
		}
		resv.push_back(res);
	}
}

五.对比分析

通过观察别人写的代码我发现我针对该问题的实现方式还不够巧妙。别人的代码实现如下图所示。

vector<int> countBits(int num) {
	vector<int> result(num+1);
	result[0]=0;
	for(int i=0;i<=num;++i)
	{
		if(i%2==1) result[i]=result[i-1]+1;
		else result[i]=result[i/2];
	}

	return result;
}

该解题方法的设计主要是考虑到了奇偶数交替变化中隐藏的规律,运用了DP(动态规划)的思想。动态规划的基本原则就是根据之前已经得到的结果,结合公式推演得到当前的结果,其特点是当前结果依赖于子问题的结果。动态规划的核心有两点:找到递推公式、确定起始状态。在本题中,递推公式的确定依赖于针对整数奇偶性的分类。具体的分类规则如下:针对奇数,在二进制表示中,奇数一定比其前面那个偶数多一个1,因为多的就是最低位的1;针对偶数,在二进制表示中,偶数中1的个数一定和除以2后得到的那个数一样多(因为最低位是0,除以2 就是右移一位,也就是把那个0 抹掉而已,所以1 的个数是不变的)。初始状态,也就是整个递推的起点,即0只有0个1。由此可以得到整个算法的实现方法。

六.题目来源

338. 比特位计数

发布了22 篇原创文章 · 获赞 0 · 访问量 1297

猜你喜欢

转载自blog.csdn.net/qq_35238352/article/details/101170132