剑指offer——二进制中1的个数

目录

  • 1. 题目描述
  • 2. 可能引起死循环的想法
  • 3. 改进后的代码
  • 4. 给面试官惊喜的代码

1. 题目描述

  • 请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如把9表示成二进制位1001,有2位是1,因此如果输入9,该函数输出2.
  • 可以进这个链接练习——牛客网

2. 可能引起死循环的想法

  • 这是一道很基本的考查二进制和位运算的面试题。
  • 题目不是很难,面试官提出问题之后,我们很快就能形成一个基本的思路:先判断整数二进制表示中最右边一位是不是1。
  • 接着把输入的整数右移一位,此时原来处于从右边数起的第二位被移到最右边了,再判断是不是1。
  • 这样每次移动一位,直到整个整数变成0为止。现在的问题变成怎么判断一个整数的最右边是不是1了。
  • 这很简单,只要把整数和1做位与运算看结果是不是0就知道了。
  • 1除了最右边的一位之外所有位都是0。
  • 如果一个整数与1做与运算的结果是1,表示该整数最右边一位是1,否则是0。
  • 基于这个思路,我们很快就能写出如下代码:
#include <stdio.h>int NumberOf1(int n)
{int count = 0;while (n != 0){if (n & 1){count++;}n >>= 1;}return count;
}int main()
{int n = 0;scanf("%d", &n);printf("%d\n", NumberOf1(n));return 0;
}
  • 当输入 9 时:

在这里插入图片描述

  • 面试官看了代码之后可能会问:把整数右移一位和把整数除以2在数学上是等价的,那上面的代码中可以把右移运算换成除以2吗?答案是否定的。
  • 因为除法的效率比移位运算要低得多,在实际编程中应尽可能地用移位运算符代替乘除法。
  • 面试官接下来可能要问的第二个问题就是:上面的函数如果输入一个负数,比如 0x80000000,运行的时候会发生什么情况?
  • 把负数0x80000000右移一位的时候并不是简单地把最高位的1移到第二位变成0x40000000而是0xC0000000。
  • 这是因为移位前是个负数,仍然要保证移位后是个负数,因此移位后的最高位会设为1。
  • 如果一直做右移运算,最终这个数字就会变成FFFFFFFF陷入死循环
  • 当输入-1时:

在这里插入图片描述

3. 改进后的代码

  • 为了避免死循环,我们可以不右移输入的数字 n。
  • 首先把 n 和 1 做与运算,判断 n 的最低为是不是 1。
  • 接着把 1 左移一位得到 2 ,再和 n 做与运算,就能判断 n 的次低位是不是 1……这样反复左移,每次都能判断 n 的其中一位是不是 1 了
  • 基于这个思路,我们可以把代码修改如下:
#include <stdio.h>int NumberOf1(int n)
{int count = 0;unsigned int flag = 1;while (flag != 0){if (n & flag){count++;}flag <<= 1;}return count;
}int main()
{int n = 0;scanf("%d", &n);printf("%d\n", NumberOf1(n));return 0;
}
  • 当输入 9 时:

在这里插入图片描述

  • 当输入 -1 时:

在这里插入图片描述

4. 给面试官惊喜的代码

  • 在分析这种算法之前,我们先来分析把一个数减去1的情况。
  • 如果一个整数不等于0,那么该整数的二进制表示中至少有一位是1。
  • 先假设这个数的最右边一位是1,那么减去1时,最后一位变成0而其他所有位都保持不变。
  • 也就是最后一位相当于做了取反操作,由1变成了0。
  • 接下来假设最后一位不是1而是0的情况。
  • 如果该整数的二进制表示中最右边1位于第m位,那么减去1时,第m位由1变成0,而第m位之后的所有0都变成1,整数中第m位之前的所有位都保持不变。
  • 举个例子:一个二进制数1100,它的第二位是从最右边数起的一个1。减去1后,第位变成0,它后面的两位0变成1,而前面的1保持不变,因此得到的结果是1011。
  • 在前面两种情况中,我们发现把一个整数减去1,都是把最右边的1变成0。
  • 如果它的右边还有0的话,所有的0都变成1,而它左边所有位都保持不变。
  • 接下来我们把一个整数和它减去1的结果做位与运算,相当于把它最右边的1变成0。
  • 还是以前面的1100为例,它减去1的结果是1011。
  • 我们再把1100和1011做位与运算,得到的结果是1000。我们把1100最右
  • 边的1变成了0,结果刚好就是1000。
  • 我们把上面的分析总结起来就是:把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0。
  • 那么一个数的二进制表示中有多少个1,就可以进行多少次这样的操作。基于这种思路,我们可以写出新的代码:
#include <stdio.h>int NumberOf1(int n)
{int count = 0;while (n != 0){n = n & (n - 1);count++;}return count;
}int main()
{int n = 0;scanf("%d", &n);printf("%d\n", NumberOf1(n));return 0;
}
  • 运行结果为:

在这里插入图片描述
最后,
恭喜你又遥遥领先了别人!

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/469061.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#,最长公共扩展(LCE,Longest Common Extention)的算法与源代码

一、最长公共扩展&#xff08;LCE&#xff09;问题 考虑一个字符串s&#xff0c;并为每对&#xff08;L&#xff0c;R&#xff09;计算从L和R开始的s的最长子字符串。 在LCE中&#xff0c;在每个查询中&#xff0c;我们必须回答从索引L和R开始的最长公共前缀的长度。 例子&am…

机器学习、深度学习、强化学习、迁移学习的关联与区别

Hi&#xff0c;大家好&#xff0c;我是半亩花海。本文主要了解并初步探究机器学习、深度学习、强化学习、迁移学习的关系与区别&#xff0c;通过清晰直观的关系图展现出四种“学习”之间的关系。虽然这四种“学习”方法在理论和应用上存在着一定的区别&#xff0c;但它们之间也…

什么是 Flet?

什么是 Flet&#xff1f; Flet 是一个框架&#xff0c;允许使用您喜欢的语言构建交互式多用户 Web、桌面和移动应用程序&#xff0c;而无需前端开发经验。 您可以使用基于 Google 的 Flutter 的 Flet 控件为程序构建 UI。Flet 不只是“包装”Flutter 小部件&#xff0c;而是…

51单片机编程基础(C语言):电子时钟(LED1602作为显示)

题目要求&#xff1a; 审题时这个题是用数码管来显示的&#xff0c;数码管显示时钟我完成了一个&#xff0c;只是要求跟他不一样&#xff0c;所以这次想用LCD1602来显示&#xff0c;所以我先用LCD1602完成&#xff0c;再用数码管完成&#xff08;其实也只要在我之前的项目基础…

《数电》理论笔记-第3章-常用组合逻辑电路及MSI组合电路模块的应用

一&#xff0c;编码器和译码器 1&#xff0c;编码器 编码:用由0和1组成的代码表示不同的事物。 编码器:实现编码功能的电路&#xff0c; 常见编码器:普通编码器、优先编码器、二进制编码器二-十进制编码器等等 1.1 三位二进制普通编码器和三位二进制优先编码器 1分58秒开始 …

洛谷_P1923 【深基9.例4】求第 k 小的数_python写法

哪位大佬可以出一下这个的题解&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;话说蓝桥杯可以用numpy库吗&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f; 这道题有一个很简单的思路就是排序完成之后再访问。 but有很大的问题&…

近十年金融资产收益率

通过掌握大类资产的历年收益率数据&#xff0c;做基于数据的投资&#xff0c;提高胜率和收益率。 下面是同花顺梳理的2014至2023大类金融资产收益率&#xff1a; 基于这个数据&#xff0c;我们再统计两项指标&#xff1a; 1. 每种资产在近十年的投资胜率&#xff08;收益率为…

哈希表 ?

哈希表 首先什么是 哈希表&#xff0c;哈希表&#xff08;英文名字为Hash table&#xff0c;国内也有一些算法书籍翻译为散列表&#xff0c;大家看到这两个名称知道都是指hash table就可以了&#xff09;。 哈希表是根据关键码的值而直接进行访问的数据结构。 这么这官方的解释…

每日一练——月落乌啼算钱

题目&#xff1a; 举例&#xff1a; 输入&#xff1a;6&#xff0c;输出&#xff1a;8.00 最开始看到这道题还有点蒙&#xff0c;但是看到他的公式想起了斐波那契数列 1,1,2,3,5,8...... 由前两个数相加得到第三个数&#xff0c;为An2An1An。 可以得出这个题目中所给的通项就…

Spark编程实验六:Spark机器学习库MLlib编程

目录 一、目的与要求 二、实验内容 三、实验步骤 1、数据导入 2、进行主成分分析&#xff08;PCA&#xff09; 3、训练分类模型并预测居民收入 4、超参数调优 四、结果分析与实验体会 一、目的与要求 1、通过实验掌握基本的MLLib编程方法&#xff1b; 2、掌握用MLLib…

《UE5_C++多人TPS完整教程》学习笔记3 ——《P4 测试多人游戏(Testing Mutiplayer)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P4 测试多人游戏&#xff08;Testing Mutiplayer&#xff09;》 的学习笔记&#xff0c;该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版&#xff0c;UP主&#xff08;也是译…

Java入门高频考查基础知识9(银盛15问万字参考答案)

JAVA刷题专栏&#xff1a;http://t.csdnimg.cn/9qscL 目录 一、Springcloud的工作原理 三、注册中心心跳是几秒 四、消费者是如何发现服务提供者的 五、多个消费者调⽤用同⼀接口&#xff0c;eruka默认的分配⽅式是什么 六、springboot常用注解&#xff0c;及其实现 七、…