解決這個問題第一想法確定是一位一位的去判斷,是1計數器+1,不然不操做,跳到下一位,十分容易,編程初學者就能夠作獲得!算法
因而很容易獲得這樣的程序:編程
int Sum1ByBin(int num) { int sum = 0; while (num) { if(sum %2 ==1) { sum ++; } sum/=2; } return sum; }
或者用牛逼的位運算:循環
int Sum1ByBin(int num) { int sum = 0; while (num) { sum += num&1; num>>1; } return sum; }
上面這兩篇代碼是用的一樣的算法, 時間複雜度是二進制的位數,因而能夠想一下,有沒有隻有與二進制中1的位數相關的算法呢?二進制
能夠考慮每次找到從最低位開始遇到的第一個1,計數器加1而後把它清零,而後繼續找下一個1。方法就是n&(n-1),這個操做對比當前位高的位沒有任何影響,程序
對低位徹底清零。舉個栗子吧!5。 5是101,第一次運算101&100 == 100,而且計數器加一,第二次運算100&011 == 0,計數器加一。循環結束啦!方法
因此5有2個1。牛逼吧! 看看代碼是怎麼實現的:時間
int Sum1byBin(int num) { int sum = 0; while(num) { num &= num-1; sum++; } return 0; }
非常簡單,這就是位運算的好處,聽說這個算法沒把位運算髮揮到極致,也沒有獲得這個算法最優解。while
請讀者先look一段代碼,看看能不能看懂是什麼功能:初學者
int Sum1byBin(int num) { num = (num&0x55555555) + ((num>>1)&0x55555555); num = (num&0x33333333) + ((num>>2)&0x33333333); num = (num&0x0f0f0f0f) + ((num>>4)&&0x0f0f0f0f); num = (num&0x00ff00ff) + ((num>>4)&&0x00ff00ff); num = (num&0x0000ffff) + ((num>>4)&&0x0000ffff); return num; }
臥槽,這個是在玩什麼中的製表符致使空格這麼大的不怪我!位運算
回想第一次遇到這個代碼的時候我第一印象,這是什麼**玩意,後來通過分析而且有高手幫助理解,這個功能正是利用了位運算,將一個數中二進制表中1 的個數算了出來。利用的是分治思想,先計算每對相鄰的2位中有幾個1,再計算相鄰的4位有一個1 ,再計算相鄰的8位、16位、32位有幾個1,到此結束,32位的機器int就是32位,因此算
到32位就夠啦!!!