🌹作者:云小逸
📝个人主页:云小逸的主页
📝Github:云小逸的Github
🤟motto:要敢于一个人默默的面对自己,==强大自己才是核心==。不要等到什么都没有了,才下定决心去做。种一颗树,最好的时间是十年前,其次就是现在!学会自己和解,与过去和解,努力爱自己。==希望春天来之前,我们一起面朝大海,春暖花开!==🤟 👏专栏:C++👏 👏专栏:Java语言👏👏专栏:Linux学习👏
👏专栏:C语言初阶👏👏专栏:数据结构👏👏专栏:备战蓝桥杯👏
@TOC
前言
今天我们继续学习算法,加油。这篇文章写的是二进制中1的个数问题。希望这篇可以有幸帮助到你,码字不易,请多多支持。
——————————————————————————————
AcWing 801. 二进制中1的个数
问题描述
请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。
例如,把 9 表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。
算法思路
这道题目也可以称为 "求数字二进制下 1 的个数" 。我们可以通过一些二进制操作来解决这个问题,在这里简单介绍几种方法:
方法一:转化为字符串
将数字转化为字符串后,遍历字符串统计字符 '1' 的数量即可。
方法二:位运算法
假设这个数字的二进制表示中第 k 位为 1,那么将它和 1 相与的结果就是 2k-1 。我们可以每次将数字和 1 做与运算,从而得到最低位是否为 1 。然后将数字无符号右移一位,继续判断下一位是否为 1 ,直到数字变为 0 为止。
例子: 00101000 (40)进行运算时结果如下:
00101000
00000001 & // 得到0
0010100 0>>1 // 右移之后变成了 101010
00000001 & // 得到1
001010 0>>1 // 右移之后变成了 10101
00000010 & // 得到0
00101 0>>1 // 右移之后变成了 1010
00000000 & // 得到0
1010 0>>1 // 右移之后变成了 0101
00000001 & // 得到1
010 0>>1 // 右移之后变成了 0010
00000000 & // 得到0
001 0>>1 // 右移之后变成了 0001
00000001 & // 得到1
000 0>>1 // 右移之后变成了 0000,最低位判断完毕。
总共有3个1。
算法实现
方法一的 C++ 实现
int numberOf1(int n) {
string s = to_string(n);
int cnt = 0;
for (auto c : s)
if (c == '1')
cnt++;
return cnt;
}
方法二的 C++ 实现
int numberOf1(int n) {
int cnt = 0;
while (n != 0) {
if (n & 1)
cnt++;
n = n >> 1;
}
return cnt;
}
时间复杂度分析
对于方法一,时间复杂度取决于将数字转化为字符串的复杂度,因此其时间复杂度与数字的大小和二进制表示中 1 的个数有关系。在最坏情况下,当数字为 INT_MAX 时,它的二进制表示有 31 位,其中包括了 1 个 '0' 和 30 个 '1',因此时间复杂度为 O(log n)。
对于方法二,需要执行 O(log n) 次循环来计算数字中 1 的个数,因此它的时间复杂度为 O(log n)。
总结
这道题目考察了对二进制操作的理解和应用。方法一字符串转换比较简单易懂,但是在性能上可能不如方法二。而方法二实现稍微复杂一些,但可以通过位运算来快速计算数字的二进制中 1 的个数,是一种高效的实现方式。
最后
十分感谢你可以耐着性子把它读完和我可以坚持写到这里,送几句话,对你,也对我:
1.把时间尺度拉长,拉长十年看当下
2.不说负面情绪,只描述事实;
3.越专注于过好自己,能量和幸运越会照顾你;
只解决问题,不做没有意义的担心,输了就认;
4.学会原谅自己,要允许自己做错事,允许自己出现情绪波动,我知道你已经很努力很努力在做好了
5.所有你害怕的、想逃避的事情,最终都要面对,既然这样不如选择坦然面对。即使结果不如人愿,没关系,至少这个过程是享受的,而不是一路带着恐惧和害怕。
最后如果觉得我写的还不错,请不要忘记==点赞==✌,==收藏==✌,加==关注==✌哦(。・ω・。)
愿我们一起加油,奔向更美好的未来,愿我们从懵懵懂懂的一枚==菜鸟==逐渐成为==大佬==。加油,为自己点赞!