一、原题原解法
官方给的解法二:
解法代码:
class Solution {
public:
vector<int> countBits(int num) {
vector<int> bits(num + 1);
int highBit = 0;
for (int i = 1; i <= num; i++) {
if ((i & (i - 1)) == 0) {
highBit = i;
}
bits[i] = bits[i - highBit] + 1;
}
return bits;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/counting-bits/solution/bi-te-wei-ji-shu-by-leetcode-solution-0t1i/
来源:力扣(LeetCode)
运行情况:
二、个人补充分析
首先我们要明白其中的几个关键的原理:
第一:位与运算:&
寻找最高有效位的时候用的代码是:i & (i - 1)==0
根据题目的意思最高有效位是:20,21,22,23
相应的二进制码是:0,10,100,1000
只有最高有效位与比起少1的数字,位与计算才是0,比如 4&3=100&011=0
解释:位与计算‘&’:是指参加运算的两个数,按二进制位进行“与”运算。
运算规则:只有两个数的二进制同时为1,结果才为1,否则为0。(负数按补码形式参加按位与运算。即 0 & 0= 0 ,0 & 1= 0,1 & 0= 0, 1 & 1= 1。
比如:5&6=101&110=100=4
第二: y为 x 的「最高有效位」。令 z=x−y,显然 0≤z<x 则 bits[x]=bits[z]+1(也就是 bits[x]=bits[z]+bits[y])
代码: bits[i] = bits[i - highBit] + 1;
分析:
输入: 0, 1, 2 , 3, 4, 5, 6, 7
二进制:0,1,10,11,100,1001,1010,1011
1的个数: 0,1, 1, 2, 1, 2, 2, 3
规律:bit[任一比最高效位数字大的数] 减去 bit[ 最高效位数]=bit[两者之差]
即:bit[4]+bit[3]=bit[7];
这就是这种方法所需要的最主要的原理了
总结:
原理一:知道最高效位的概念
原理二: 最高效位的运算
接下来补充一点其余有些难懂的地方:
比如
第一:
vector bits(num + 1);
查阅资料发现,这个创建对象名还调用了指定的构造函数。因为这个构造函数在LeeCode的类Solution内部,我们看不到。
不过可以猜想,这里面含有像new这样开辟空间的函数,所以需要加上(num+1)的参数,而且num+1正好是0到num需要的空间大小。有意思的是,这个开辟空间之后为自动初始化为0;
第二:
bit[]数组为什么没有赋值,因为i是从1开始递推的。所以后面的数组bit[i]都在前面找得到,bit[1]是从bit[0]推过来的,bit[0]在之前调用 vector bits(num + 1);就会被初始化为0,
下面是我在官方的代码上加了点自己的注释(VS2019):
#include<iostream>
#include<vector>
using namespace std;
void disaplay(vector<int> &temp)
{
typename vector<int>::iterator it;
for (it = temp.begin(); it < temp.end(); it++)
{
cout << *it;
}
cout << endl;
}
class Solution {
public:
vector<int> countBits(int num) {
vector<int> bit(num+1);//调用特殊的构造函数,并且默认值都是0,所以没必要给bit[0]=0;
int highbit = 0;
for (int i=1;i<=num;i++)
{
if ((i & (i - 1)) == 0)//判断是否是最高有效位,i会大于highbit
highbit = i;
bit[i] = bit[i - highbit] + 1;//bit[highbit]+bit[i]=bit[highbit+i],i是递进的,i以前的bit都已经存入了
}
return bit;
}
};
int main()
{
Solution solu;
vector<int> temp;
temp = solu.countBits(2);
disaplay(temp);
return 0;
}
如果觉得对你有帮助,那就赞一下吧!
如果你觉得有不足之处或者意见,可以评论指出交流!
本文详细分析了LeetCode第338题的C++官方解法二,重点讲解了位与运算在解决此问题中的关键作用。通过例子解释了如何找到最高有效位,并展示了如何利用位运算求解位计数问题。此外,还探讨了代码中初始化vector的细节和数组更新的逻辑。

被折叠的 条评论
为什么被折叠?



