剑指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.rhkb.cn/news/257016.html

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

相关文章

idea: 无法创建Java Class文件(SpringBoot)已解决

第一&#xff1a;点击file-->project Sructure... 第二步&#xff1a;点击Moudules 选择自己需要创建java的文件夹&#xff08;我这里选择的是main&#xff09;右键点击Sources&#xff0c;然后点击OK即可 然后就可以创建java类了

Java+SpringBoot实习管理系统探秘

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

Vue学习笔记(三)常用指令、生命周期

Vue学习笔记&#xff08;三&#xff09;常用指令 vue指令&#xff1a;html标签上带有 v- 前缀的特殊属性&#xff0c;不同的指令具有不同的含义&#xff0c;可以实现不同的功能。 常用指令&#xff1a; 指令作用v-for列表渲染&#xff0c;遍历容器的元素或者对象的属性v-bind…

MIT-Missing Semester_Topic 3:Editors (Vim) 练习题

文章目录 练习一练习二练习三练习四练习五练习六练习七练习八 本 Topic 的 MIT 讲解网页&#xff08;练习题未给解答&#xff09; 练习一 自行完成 vimtutor。vimtutor 是 Vim 本身附带的一个入门教程&#xff0c;在 shell 中直接输入 vimtutor 便能运行。注意该教程在 8024 大…

书生·浦语大模型第四课作业

基础作业&#xff1a; 构建数据集&#xff0c;使用 XTuner 微调 InternLM-Chat-7B 模型, 让模型学习到它是你的智能小助手&#xff0c;效果如下图所示&#xff0c;本作业训练出来的模型的输出需要将不要葱姜蒜大佬替换成自己名字或昵称&#xff01; 1.安装 # 如果你是在 Int…

三、案例 - MySQL数据迁移至ClickHouse

MySQL数据迁移至ClickHouse 一、生成测试数据表和数据1.在MySQL创建数据表和数据2.在ClickHouse创建数据表 二、生成模板文件1.模板文件内容2.模板文件参数详解2.1 全局设置2.2 数据读取&#xff08;Reader&#xff09;2.3 数据写入&#xff08;Writer&#xff09;2.4 性能设置…

【每日一题】牛客网——链表的回文结构

✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有限&#xff0c;欢迎各位大佬指点&#xff0c;相互学习…

【JavaEE进阶】 图书管理系统开发日记——陆

文章目录 &#x1f38b;前言&#x1f343;删除图书&#x1f6a9;约定前后端交互接口&#x1f6a9;完善前端代码&#x1f6a9;接口测试 &#x1f38d;批量删除&#x1f6a9;约定前后端交互接口&#x1f6a9;实现后端服务器代码&#x1f388;控制层&#x1f388;业务层&#x1f3…

查看系统进程信息的Tasklist命令

Tasklist命令是一个用来显示运行在本地计算机上所有进程的命令行工具&#xff0c;带有多个执行参数。另外&#xff0c;Tasklist可以代替Tlist工具。通过任务管理器&#xff0c;可以查看到本机完整的进程列表&#xff0c;而且可以通过手工定制进程列表方式获得更多进程信息&…

Vue源码系列讲解——模板编译篇【二】(整体运行流程)

目录 1. 整体流程 2. 回到源码 3. 总结 1. 整体流程 上篇文章中我们说了&#xff0c;在模板解析阶段主要做的工作是把用户在<template></template>标签内写的模板使用正则等方式解析成抽象语法树&#xff08;AST&#xff09;。而这一阶段在源码中对应解析器&…

港口码头航吊远距离相位测距仪|传感器PHR-120100配置使用说明

港口码头航吊远距离相位测距仪|传感器PHR-120100广泛应用于港口码头、航车、位移监测、形变监测、钢铁、堆垛机、龙门吊等领域。 本文重点介绍港口码头航吊远距离相位测距仪|传感器PHR-120100配置使用说明。 一、布局介绍 二、按键介绍 三、指示灯说明 四、显示屏操作说明 …

Git中Idea操作git及Git Flow

目录 一、Idea中使用Git 1.idea配置Git和Gitee 2.实践操作 1.将本地项目推送到远程 2.从远程库克隆项目到本地 二、Git Flow 1.什么是Git Flow 2.工作流程 3.实践操作 一、Idea中使用Git 1.idea配置Git和Gitee 第一步&#xff1a;设置git.exe的安装路径 在设置中的…

蓝牙BLE学习-安全

1.基本概念 蓝牙标准规定了5种基本的安全服务 身份验证:根据通信设备的蓝牙地址验证其身份。蓝牙不提供本地用户身份验证。保密性:确保只有授权的设备才能访问和查看传输的数据&#xff0c;防止窃听造成的信息泄露。授权(Authorization):在允许设备使用某项服务之前&#xff…

深度测评:ONLYOFFICE 桌面编辑器 v8.0新功能

目录 前言 一、PDF表单处理&#xff1a;提升办公效率 二、RTL&#xff08;从右到左&#xff09;支持&#xff1a;满足不同语言习惯 三、Moodle集成&#xff1a;教育行业的新助力 四、本地界面主题&#xff1a;个性化办公体验 五、性能优化与稳定性提升 六、性能与稳定性…

C++ Qt框架开发 | 基于Qt框架开发实时成绩显示排序系统(3) 保存表格数据

对上两篇篇的工作C Qt框架开发| 基于Qt框架开发实时成绩显示排序系统&#xff08;1&#xff09;-CSDN博客和C Qt框架开发 | 基于Qt框架开发实时成绩显示排序系统&#xff08;2&#xff09;折线图显示-CSDN博客继续优化&#xff0c;增加一个保存按钮&#xff0c;用于保存成绩数据…

不可错过!10款超赞实用插件框架

Cocos 游戏开发十八般武器&#xff0c;尽在 Cocos Store 今天给大家分享10款实用插件与框架&#xff01; 1. 快闪-Tab标签王(prefab标签栏) 作者&#xff1a;嘉年华&#xff08;gameWs&#xff09; 《快闪-标签王》插件&#xff0c;解决了日常开发过程中&#xff0c;经常需要通…

一、Docker部署MySQL

Docker部署MySQL 一、安装Docker二、拉取MySQL镜像1.选择拉取版本2.拉取镜像 三、启动MySQL1.确定好挂载目录2.启动3.查看是否启动4.开启远程访问权限 一、安装Docker 安装教程&#xff1a;https://qingsi.blog.csdn.net/article/details/131270071 二、拉取MySQL镜像 1.选择…

Microsoft OneNote 图片文字提取

Microsoft OneNote 图片文字提取 1. 文件 -> 新建 -> 我的电脑 -> 名称 -> 位置 -> 创建笔记本2. 插入图片​​​3. 复制图片中的文本References 1. 文件 -> 新建 -> 我的电脑 -> 名称 -> 位置 -> 创建笔记本 ​ 2. 插入图片 ​​​3. 复制图片…

【lesson52】 线程概念

文章目录 线程学习前的了解知识理解线程 线程学习前的了解知识 线程在进程内部执行&#xff0c;是OS调度的基本单位 OS可以做到让进程对进程地址空间进行资源的细粒度划分 比如malloc一块内存空间&#xff0c;我们拿到的一般都是起始位置&#xff0c;但是最终位置我们一般都不…

kali系统概述、nmap扫描应用、john破解密码、抓包概述、以太网帧结构、抓包应用、wireshark应用、nginx安全加固、Linux系统加固

目录 kali nmap扫描 使用john破解密码 抓包 封装与解封装 网络层数据包结构 TCP头部结构​编辑 UDP头部结构 实施抓包 安全加固 nginx安全 防止缓冲区溢出 Linux加固 kali 实际上它就是一个预安装了很多安全工具的Debian Linux [rootmyhost ~]# kali resetkali …