剑指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.mzph.cn/news/683247.shtml

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

相关文章

Selenium图表自动化开篇

目录 前言&#xff1a; 使用 Canvas 或者 SVG 渲染 选择哪种渲染器 代码触发 ECharts 中组件的行为 前言&#xff1a; 图表自动化一直以来是自动化测试中的痛点&#xff0c;也是难点&#xff0c;痛点在于目前越来越多公司开始构建自己的BI报表平台但是没有合适的自动化测试…

Shell 学习笔记(三)-shell变量

Shell 语言是一种动态类型和弱类型语言, 因此,在Shell中无需显示地声明变量, 且变量的类型会根据不同的操作符而发生变化. 静态类型语言: 在程序编译期间就确定变量类型的语言, 如java, C等 动态类型语言: 在程序运行期间才确定变量类型的语言, 如PHP, Python等. 一 shell变量…

高中信息技术—数据采集与编码(一)

计算机技术的应用&#xff0c;使得数据的处理方式发生了巨大的转变&#xff0c;要用计算机处理这些数据&#xff0c;需要对采集到的数据进行一定的转换。 采集方式 1.人工采集—观察、实验 2.机器采集 互联网—网络爬虫 传感器—自然信源 数字化 信息可用模拟信号或数字信号表…

MySQL学习记录——구 复合查询

文章目录 1、基本查询2、多表查询3、自连接4、子查询1、多行子查询2、多列子查询3、from句中的子查询 5、合并查询 1、基本查询 看一些例子&#xff0c;不关心具体内容&#xff0c;只看写法 //查询工资高于500或岗位为MANAGER的雇员, 同时还要满足他们的姓名首字母为大写的J …

Docker的常见命令以及命令别名

常见命令 命令说明docker pull拉取镜像docker push推送镜像到DockerRegistrydocker images查看本地镜像docker rmi删除本地镜像docker run创建并允许容器docker stop停止指定容器docker start启动指定容器docker restart重新启动容器docker rm删除指定容器docker ps查看容器do…

ClickHouse--04--数据库引擎、Log 系列表引擎、 Special 系列表引擎

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1.数据库引擎1.1 Ordinary 默认数据库引擎1.2 MySQL 数据库引擎MySQL 引擎语法字段类型的映射 2.ClickHouse 表引擎3.Log 系列表引擎几种 Log 表引擎的共性是&#…

opencv通道分离与合并

void QuickDemo::channels_demo(Mat & image) {std::vector<Mat>mv;//通道分离合并split(image,mv);//原图 指针(Mat)imshow("蓝色", mv[0]);imshow("绿色", mv[1]);imshow("红色", mv[2]); } split(image,mv);//原图 指针(Mat) 这里…

学习笔记20:牛客周赛32

D 统计子节点中1的个数即可&#xff08;类似树形dp&#xff1f;&#xff09; #include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<vector> #include<set> #include<map>u…

Rust 数据结构与算法:5栈:用栈实现前缀、中缀、后缀表达式

3、前缀、中缀和后缀表达式 计算机是从左到右处理数据的,类似(A + (B * C))这样的完全括号表达式,计算机如何跳到内部括号计算乘法,然后跳到外部括号计算加法呢? 一种直观的方法是将运算符移到操作数外,分离运算符和操作数。计算时先取运算符再取操作数,计算结果则作为…

HTML5+CSS3+JS小实例:锥形渐变彩虹按钮

实例:锥形渐变彩虹按钮 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /…

maven创建webapp+Freemarker组件的实现

下载安装配置maven Maven官方版下载丨最新版下载丨绿色版下载丨APP下载-123云盘123云盘为您提供Maven最新版正式版官方版绿色版下载,Maven安卓版手机版apk免费下载安装到手机,支持电脑端一键快捷安装https://www.123pan.com/s/9QRqVv-TcUY.html链接为3.6.2-3.6.3的版本 下载解…

LLVM的中间表示

概括 选择编译器IR的决策很重要&#xff0c;它决定了优化过程将拥有多少信息来使代码运行得更快。 一方面非常高层级的IR允许优化器轻松地提取原始源代码的相关信息。 另一方面&#xff0c;低层的IR更加贴近目标机器&#xff0c;这样编译器更容易为特定的硬件生成相应的代码…

RH850从0搭建Autosar开发环境【2X】- Davinci Configurator之XCP模块配置详解(上)

XCP模块配置详解 - 上 一、XCP模块配置项处理1.1 Tx Pdu配置项二、XCP模块其他配置项2.1 参数XcpMainFunctionPeriod2.2 参数XcpOnCanEnabled2.3 容器XcpOnCan总结从本节开始先专注与配置项错误处理以及构建Autosar Rh850的最小系统搭建。 XCP模块在汽车电子各控制器中处于十分…

【Java记】数据类型与变量

一、数据类型 在Java中数据类型主要分为两类&#xff1a;基本数据类型和引用数据类型。基本数据类型有四类八种&#xff1a; 四类&#xff1a;整型、浮点型、字符型以及布尔型八种&#xff1a; 数据类型 关键字 内存占用 范围 字节型 byte 1 字节 -128~ 127 短整型 …

高程 | 数组、指针与字符串(c++)

文章目录 &#x1f4da;数组&#x1f407;数组的概念&#x1f407;数组的声明与使用&#x1f407;数组的存储与初始化&#x1f407;数组作为函数参数&#x1f407;对象数组 &#x1f4da;指针&#x1f407;内存空间的访问方式&#x1f407;指针变量的声明&#x1f407;指针运算…

蓝桥杯嵌入式第10届真题(完成) STM32G431

蓝桥杯嵌入式第10届真题(完成) STM32G431 题目 main.c /* USER CODE BEGIN Header */ /********************************************************************************* file : main.c* brief : Main program body********************************…

【C语言】指针练习篇(下),深入理解指针---指针练习题【图文讲解,详细解答】

欢迎来CILMY23的博客喔&#xff0c;本期系列为【C语言】指针练习篇&#xff08;下&#xff09;&#xff0c;深入理解指针---指针练习题【图文讲解,详细解答】&#xff0c;图文讲解指针练习题&#xff0c;带大家更深刻理解指针的应用&#xff0c;感谢观看&#xff0c;支持的可以…

文件操作详解

文章目录 目录1. 为什么使用文件2. 什么是文件2.1 程序文件2.2 数据文件2.3 文件名 3. 文件的打开和关闭3.1 文件指针3.2 文件的打开和关闭 4. 文件的顺序读写5. 通讯录的改造6. 文件的随机读写6.1 fseek6.2 ftell6.3 rewind 7. 文本文件和二进制文件8. 文件读取结束的判定9. 文…

『运维备忘录』之 Lsof 命令详解

运维人员不仅要熟悉操作系统、服务器、网络等只是&#xff0c;甚至对于开发相关的也要有所了解。很多运维工作者可能一时半会记不住那么多命令、代码、方法、原理或者用法等等。这里我将结合自身工作&#xff0c;持续给大家更新运维工作所需要接触到的知识点&#xff0c;希望大…

Excel模板2:进度条甘特图

Excel模板2&#xff1a;进度条甘特图 ‍ 今天复刻B站up【名字叫麦兜的狗狗】的甘特图&#xff1a;还在买Excel模板吗&#xff1f;自己做漂亮简洁的甘特图吧&#xff01;_哔哩哔哩_bilibili 阿里网盘永久分享&#xff1a;https://www.alipan.com/s/cXhq1PNJfdm 当前效果&…