【4.15】求二进制数中1的个数【每日一题】

2024-01-13 11:58

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

【4.15】求二进制中1的个数。例如,10=1010,1的个数为2。【每日一题】

此题主要考查位运算,当然不会用位运算的人可能会这么写:

1.可能是最笨的方法了

int numOfOne(unsigned num) {int count = 0;while (num) {count += num % 2;num /= 2;}return count;
}


使用位运算的原因是位运算比乘法要快,这是与计算机的硬件实现相关的。下面是使用位运算中的一种比较弱多解法,好处是逻辑清楚,易懂。


2.用位运算来代替方法1中的除法和取模运算

int numOfOne(unsigned num) {int count = 0;while (num) {count += num & 1;num >>= 1;}return count;
}


方法2中的方法已经比方法1中的方法好很多了,但是有没有更好的方法呢?下面是编程之美中给出的方法


3.只用一次位运算

int hammingWeight(uint32_t n) {int count = 0;while (n) {n = n & n - 1;++count;}return count;
}


这个方法中,每次循环仅用了一次位运算,从这里已经比方法2省了一次位运算,另外,我们可以发现如下规律:

  1. 当n不为0时,n-1总是从把n中最后一个1(二进制位)改为0(二进制位),同时将其后的所有位置0,而与此同时对于前面的所有位,n与n-1每一位均相同,因此&操作并不会改变前面所有位数的值。这样n & (n - 1)的最终效果是把n的最后一个1置0,因此我们给count加1
  2. 在每次循环时,总是找到n的最后一个1去操作,因此跳过了n所有二进制位中后面的连续的多个0位,可以有效减少循环执行次数
如前所述,方法3中循环可以跳过二进制位中的0位以减少循环执行次数,我们举例如下:

【例】 对于十进制数100,其二进制表示位1100100
  • 对于方法2,循环将执行7次
次数执行前num值执行后num值执行后count值
111001001100100
2110010110010
31100111001
411001101
5110111
61112
7103


  • 对于方法3,循环执行3次
次数执行前n值执行后n值执行后count值
1110010011000001
2110000010000002
3100000003


从例子中可以看出,方法3可以显著减少循环的执行次数。


这篇关于【4.15】求二进制数中1的个数【每日一题】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

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

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

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

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

每日一练7:简写单词(含链接)

1.链接 简写单词_牛客题霸_牛客网 2.题目 3.代码1(错误经验) #include <iostream>#include <string>using namespace std;int main() {string s;string ret;int count = 0;while(cin >> s)for(auto a : s){if(count == 0){if( a <=

【每日刷题】Day113

【每日刷题】Day113 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 🌼文章目录🌼 1. 91. 解码方法 - 力扣(LeetCode) 2. LCR 098. 不同路径 - 力扣(LeetCode) 3. 63. 不同路径 II - 力扣(LeetCode) 1. 91. 解码方法 - 力扣(LeetCode) //思路:动态规划。 cl

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记录进位,如果有字符没处理完或者有进位,则循环处理。两个字符串对

力扣 739. 每日温度【经典单调栈题目】

1. 题目 理解题意: 1.1. 给一个温度集合, 要返回一个对应长度的结果集合, 这个结果集合里面的元素 i 是 当前 i 位置的元素的下一个更高温度的元素的位置和当前 i 位置的距离之差, 若是当前元素不存在下一个更高温度的元素, 则这个位置用0代替; 2. 思路 本题用单调栈来求解;单调栈就适用于来求当前元素左边或者右边第一个比当前元素大或者小的元素;【单调栈:让栈中的元素保持单调