剑指offer——面试题10输入一个十进制整数,统计其中二进制1的个数
时间:2022-05-03
本文章向大家介绍剑指offer——面试题10输入一个十进制整数,统计其中二进制1的个数,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
/**
* 题目:输入一个十进制整数,统计其中二进制1的个数
* @author 大闲人柴毛毛
*/
public class CountBitOne {
/**
* 这个问题最直观的思路:
* 将输入的整数转换成二进制数,
* 再把这个二进制数转换成字符数组,
* 最后遍历数组,统计1的个数。
*
* 使用数组需要开辟额外的内存空间,
* 若在不能使用Java相关类库的情况下,
* 要实现十进制向二进制数组的转化实属不易。
* 且该方法需要完整遍历数组,因此需要n次比较。
*
* 下面我们探求更高效的方法。
*/
/**
* 这道题涉及到二进制,因此我们应当敏锐地察觉到使用位运算来解决问题!
*
* 位运算具有如下特性:
* 1与一个二进制数进行与运算,若最低位是1,则运算的结果为1,否则结果为0。
*
* 因此,让输入的数与1进行与运算,每运算一次便统计当前结果是否为1,并将数右移一位,
* 当该数为0时统计结束。
*
* 代码实现如下:
*/
public static int countBitOne_1(int n){
//n中1的个数
int count = 0;
while(n!=0){
//判断当前运算结果是否为1
if((n&1)==1)
count++;
//将n右移一位
n = n >> 1;
}
return count;
}
/**
* 上述方法有个严重的bug!
* 若一个正数右移n位,则需要用n个1来补齐最高位。
* 因此,当一个正数右移了若干次之后,它的所有位置都被1取代,
* 此时与1进行与运算的结果永远是1,从而出现了死循环。
*
* 如何解决呢?
*
* 出现上述情况的原因有两个:1.右移、2.正数,
* 只要破坏了这两个条件中的任何一个,就能避免死循环的现象。
* 由于本题的输入要求中包含了正整数,因此我们只能破坏第一个条件。
*
* 虽然右移与正负有关,但左移与正负无关!
* 并且要达到和方法1一样的效果,我们就让“00000001”这个序列左移。
*
* 代码如下:
*/
public static int countBitOne_2(int n){
//n中1的个数
int count = 0;
//进行左移的序列00000001
int flag = 1;
//当flag不为0的时候循环
while(flag!=0){
//若当前与运算结果不为0,则表示n当前位置是1
if((n&flag) != 0)
count++;
//flag左移一位
flag = flag << 1;
}
return count;
}
/**
* 这种方式不需要额外的内存空间,
* 而且十进制位运算的过程中,进制的转化由JVM完成,无需程序猿手动实现。
* 这种方法的时间复杂度为O(n),需要进行n次比较。
*
* 下面介绍更高效的方式。
*/
/**
* 如果将一个二进制数-1,那么该二进制数最右侧的1将会变成0,1后面的0均变成1,1前面的数保持不变。
* 也就是说,如果一个二进制数-1,那么该数最右侧的1及1右侧的所有数均变成相反数。
* 如果把这个数和原数与运算,那么最右侧的那个1前面的数将不变,1及1右侧的所有数均变为0。
* 也就是说,进行一次上述的运算后,原数最右侧的那个1将会变成0,
* 那么只要重复上述操作,当原数变成0时,循环的次数就是1的个数。
*
* 代码如下:
*/
public static int countBitOne_3(int n){
//n中1的个数
int count = 0;
while(n!=0){
n = n & (n-1);
count++;
}
return count;
}
}
- 软件更新时候出现和原包名冲突
- 一个数字截取引发的精度问题(三)
- HTML生成PDF(c#)
- 一个数字截取引发的精度问题(二)
- 【独家推送】GoogLeNet构建技术分析因子的模式识别基于TensorFlow
- 一个数字截取引发的精度问题(一)
- 基于TLS1.3的微信安全通信协议mmtls介绍
- 在 WCF 中使用高效的 BinaryFormatter 序列化
- Visual Studio 2012 中的ASP.NET Web API
- gradeview可拖动效果实现
- 【Python量化投资】拟合具有非平稳特征的神经网络对股票进行预测
- 使同事羡慕不已的8个npm命令
- JavaScript代码风格要素
- 从 WebAPI Beta 更新到WebAPI RC
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- laravel unique验证、确认密码confirmed验证以及密码修改验证的方法
- laravel 如何实现引入自己的函数或类库
- PHP实现15位身份证号转18位的方法分析
- Yii框架的redis命令使用方法简单示例
- Laravel如何实现自动加载类
- 在Laravel中实现使用AJAX动态刷新部分页面
- laravel 自定义常量的两种方案
- Thinkphp页面跳转设置跳转等待时间的操作
- Laravel 创建可以传递参数 Console服务的例子
- laravel实现查询最后执行的一条sql语句的方法
- 解决laravel groupBy 对查询结果进行分组出现的问题
- laravel批量生成假数据的方法
- 对laravel in 查询的使用方法详解
- PHP使用redis位图bitMap 实现签到功能
- thinkphp5+layui实现的分页样式示例