191. Number of 1 Bits二进制中1的个数

2024-01-04 19:32
文章标签 二进制 个数 number 191 bits

本文主要是介绍191. Number of 1 Bits二进制中1的个数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目描述

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

解答

错误的,可能引起死循环解法

  先判断整数二进制表示中最右边一位是不是1。接着把输入的整数右移一位,此时原来处于右边起的第二位被移到最右边,再判断它是不是1。这样每次移动一位,直到整个整数变成0为止。
  那么如何判断一个整数的最右边是不是1。只要把整数和1做按位与运算,看结果是否为0就可以判断。1除了最右边的一位以外,所有的位都是0。如果一个整数与1做按位与运算的结果是1,表示该整数最右边一位是1,否则是0。

int NumberOf1(int n)
{int count = 0;while(n){if(n&1)++count;n = n>>1;}return count;
}

除法的效率要比位移运算低得多,在实际编程中应尽可能用位移运算代替除法。

对于上面的方法,如果输入是一个负数,例如0x80000000时,将负数 0x80000000右移一位的时候,并不是简单把最高位的1移到第二位变成0x40000000,而是 0xC0000000。这是因为移位前是个负数,以为后仍然要是负数,所以移位后最高位会置为1。如果一直做右移运算,最终这个数字会变成0xFFFFFFFF,是算法陷入死循环。

常规解法

  为了避免死循环,我们可以不右移输入的数字n。首先把n和1做按位与运算,判断n的最低位是不是1。接着把1左移一位得到2,再和n做与运算,就能判断n的次低位是不是1……这样反复左移,每次都能判断n的其中一位是不是1。
  

class Solution {
public:int  NumberOf1(int n) {int flag = 1;int count = 0;while(flag){if(n&flag)++count;flag  = flag<<1;}return count;}
};

优化的解法

  首先分析一个数减去1的情况。如果一个整数不等于0,那么该整数的二进制表示中至少有一位是1。
  先假设这个数的最右边一位是1,那么减去1时,最右边一位变成0,而其他所有位都保持不变。也就是说最右边一位相当于做了取反操作,由1变成了0。
  下面假设最后一位不是1的情况。如果该整数的二进制表示中最右边的1位于第m位,那么减去1时,第m位由1变成0,而第m位之后的所有0都变成1,m位之前的所有位都保持不变。
  在上面两种情况中,我们发现一个整数减去1,都会把其二进制表示中最右边的1变成0。如果最右边的1的右边还有0的话,则都会变成1,而它左边的所有位都保持不变。
  最后,我们把一个整数和它减去1的结果做位于运算,相当于把它最右边的1变成0。那么一个整数的二进制表示中有多少个1,就可以进行多少次这样的运算。
  

class Solution {
public:int  NumberOf1(int n) {int count = 0;while(n){++count;n = n&(n-1);}return count;}
};

这篇关于191. Number of 1 Bits二进制中1的个数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/570362

相关文章

spoj705( 求不相同的子串个数)

题意:求串s的不同子串的个数 解题思路:任何子串都是某个后缀的前缀,对n个后缀排序,求某个后缀的前缀的个数,减去height[i](第i个后缀与第i-1 个后缀有相同的height[i]个前缀)。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstrin

usaco 1.2 Name That Number(数字字母转化)

巧妙的利用code[b[0]-'A'] 将字符ABC...Z转换为数字 需要注意的是重新开一个数组 c [ ] 存储字符串 应人为的在末尾附上 ‘ \ 0 ’ 详见代码: /*ID: who jayLANG: C++TASK: namenum*/#include<stdio.h>#include<string.h>int main(){FILE *fin = fopen (

XTU 1233 n个硬币连续m个正面个数(dp)

题面: Coins Problem Description: Duoxida buys a bottle of MaiDong from a vending machine and the machine give her n coins back. She places them in a line randomly showing head face or tail face o

题目1380:lucky number

题目1380:lucky number 时间限制:3 秒 内存限制:3 兆 特殊判题:否 提交:2839 解决:300 题目描述: 每个人有自己的lucky number,小A也一样。不过他的lucky number定义不一样。他认为一个序列中某些数出现的次数为n的话,都是他的lucky number。但是,现在这个序列很大,他无法快速找到所有lucky number。既然

O(n)时间内对[0..n^-1]之间的n个数排序

题目 如何在O(n)时间内,对0到n^2-1之间的n个整数进行排序 思路 把整数转换为n进制再排序,每个数有两位,每位的取值范围是[0..n-1],再进行基数排序 代码 #include <iostream>#include <cmath>using namespace std;int n, radix, length_A, digit = 2;void Print(int *A,

通信工程学习:什么是2ASK/BASK二进制振幅键控

2ASK/BASK:二进制振幅键控         2ASK/BASK二进制振幅键控是一种数字调制技术,其全称是二进制振幅键控(Binary Amplitude Shift Keying)。该技术通过改变载波的振幅来传递二进制数字信息,而载波的频率和相位则保持不变。以下是关于2ASK/BASK二进制振幅键控的详细解释: 一、2ASK/BASK二进制振幅键控的基本原理 1、振幅键控:

1 模拟——67. 二进制求和

1 模拟 67. 二进制求和 给你两个二进制字符串 a 和 b ,以二进制字符串的形式返回它们的和。 示例 1:输入:a = "11", b = "1"输出:"100"示例 2:输入:a = "1010", b = "1011"输出:"10101" 算法设计 可以从低位到高位(从后向前)计算,用一个变量carry记录进位,如果有字符没处理完或者有进位,则循环处理。两个字符串对

Jenkins 通过 Version Number Plugin 自动生成和管理构建的版本号

步骤 1:安装 Version Number Plugin 登录 Jenkins 的管理界面。进入 “Manage Jenkins” -> “Manage Plugins”。在 “Available” 选项卡中搜索 “Version Number Plugin”。选中并安装插件,完成后可能需要重启 Jenkins。 步骤 2:配置版本号生成 打开项目配置页面。在下方找到 “Build Env

Leetcode67---二进制求和

https://leetcode.cn/problems/add-binary/description/ 给出的两个二进制,我们可以从最后开始往前运算。 给当前短的一位前面补充0即可。 class Solution {public String addBinary(String a, String b) {//给的就是二进制字符串 最后一位开始遍历 如果没有就补充0?StringBuil

二进制的匹配问题

最近做了点搜索和背包的题目,发现这个二进制的匹配很是好用,所以写一篇二进制的匹配来作为自我总结; 首先我们要知道二进制的运算符,和他们的运算规则; ABA&BA|BA^B00000010111001111110 运算符有三种‘&’ , ‘|’ ,  ‘^'  或,且,异或,运算的规则在表中可以看到,想想这个规则我们可以做很多事情! 首先,每个十进制的数都会对应一个唯一的二进