求二进制数中1的个数
<<編程之美>>中有這么個(gè)題目:對(duì)于一個(gè)字節(jié)的無(wú)符號(hào)整形變量,求其二進(jìn)制表達(dá)形式中“1”的個(gè)數(shù)。
基礎(chǔ)算法:輾轉(zhuǎn)相除法
輾轉(zhuǎn)相除法是十進(jìn)制采用的算法,該算法如下:
int count_one_cnt(int value) {int cnt = 0;while (value){if (value % 2 == 1){cnt += 1;}value /= 2;}return cnt; }上述算法的時(shí)間復(fù)雜度O(logV)(V是value比特?cái)?shù)),上述算法的操作對(duì)象的級(jí)別是“數(shù)”級(jí)別的,題目的要求是“位”級(jí)別的,因此如果能夠通過(guò)位運(yùn)行完成題目要求功能,將會(huì)更加高效:1)除法采用右移實(shí)現(xiàn);2)通過(guò)與1位與運(yùn)算判斷是否有1的存在。
int count_one_cnt(int value) {int cnt = 0;while (value){cnt += value & 1;value >>= 1;}return cnt; }位與法:
上面的兩個(gè)算法時(shí)間復(fù)雜度均依賴于欲求的數(shù)據(jù)類(lèi)型在存儲(chǔ)空間中占有的比特?cái)?shù),位與法算法復(fù)雜度則僅與待求數(shù)據(jù)中1的個(gè)數(shù)相關(guān)。首先,觀察某個(gè)數(shù)a與a-1:在二進(jìn)制下,a-1在最右端加上1就等于a,a與a-1進(jìn)行位與運(yùn)算則會(huì)消除最右邊的1,可以從以下角度理解;
1)a與a-1僅差一個(gè)1,而這個(gè)1是從a-1最低端加上便等于a
2)假設(shè)a最低端出現(xiàn)的位置pos,pos后面均是0,因此與b位與運(yùn)算,pos位置后面均是0
3)a-1的對(duì)應(yīng)pos位置,一定是0。假設(shè)a-1在pos位置等于1,a-1后面必然均是0,否則a-1將會(huì)大于a,但根據(jù)1)a等于a-1處最低端位加1,而a-1從pos位置開(kāi)始均是0,在a-1最低端位加1得到的a,在pos位置到最低端一定有一個(gè)1,與2)矛盾。
雖然理解起來(lái)有些繞彎,但是代碼卻是非常簡(jiǎn)潔的:
int count_one_cnt(int value) {int cnt = 0;while (value){value &= value-1;cnt += 1;}return cnt; }位圖法:
<<編程之美>>提到了這種方法:8bit的無(wú)符號(hào)整數(shù)的范圍是[0, 255),因此直接將256個(gè)數(shù)還有的1位數(shù)做出表的形式,以時(shí)間換空間~實(shí)現(xiàn)方法在此省略。
Hamming weight方法:
Hamming weight:是指在給定的字符串中,所有不等于0的字符的個(gè)數(shù),在一串二進(jìn)制的字符串中,等于該二進(jìn)制中1的個(gè)數(shù)。Hamming weight方法的一種快速實(shí)現(xiàn),采用了“隔位相加”的方法:相鄰位相加,并存在與當(dāng)前位置中。算法過(guò)程如下(來(lái)源與維基百科):
可以從下圖快速理解算法的執(zhí)行過(guò)程:
實(shí)現(xiàn)方法在此不一一列出,有興趣可以參考維基百科中給出了三種實(shí)現(xiàn)方法~
轉(zhuǎn)載于:https://www.cnblogs.com/wangbogong/p/3240951.html
總結(jié)
以上是生活随笔為你收集整理的求二进制数中1的个数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 关于android 图像格式问题
- 下一篇: dos网络命令