自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一次搞透,面試中的數(shù)1問題的五種方法!

開發(fā) 開發(fā)工具
面試中,除了TopK,是否被問過:求一個(gè)正整數(shù)的二進(jìn)制表示包含多少個(gè)1?到底有幾種方法,這些思路里蘊(yùn)含的優(yōu)化思路究竟是怎么樣的,今天和大家聊一聊。

面試中,除了TopK,是否被問過:求一個(gè)正整數(shù)的二進(jìn)制表示包含多少個(gè)1?

畫外音:姊妹篇《一次搞透,面試中的TopK問題!》。

[[443193]]

例如:

  1. uint32_t i=58585858

i的二進(jìn)制表示是:

  1. 0000 0011 0111 1101 1111 0011 0000 0010 

于是,i的二進(jìn)制表示包含15個(gè)1。

到底有幾種方法,這些思路里蘊(yùn)含的優(yōu)化思路究竟是怎么樣的,今天和大家聊一聊。

一、位移法。

思路:既然輸入n是uint32,每次取n的最低位,判斷是不是1,位移32次,循環(huán)判斷即可。

偽代碼:

  1. do{ 
  2.     if ((n&1)==1){ 
  3.        result++; 
  4.     } 
  5.     n>>= 1; 
  6.     i++; 
  7. } while(i<32); 

分析:不管n的二進(jìn)制表示里包含多少個(gè)1,都需要循環(huán)計(jì)算32次,比較耗時(shí)。有沒有可能,每次消除掉一個(gè)1,這樣來降低計(jì)算次數(shù)呢?

二、求與法。

觀察一下n與n-1這兩個(gè)數(shù)的二進(jìn)制表示:

(1)最末位一個(gè)1會(huì)變成0;

(2)最末位一個(gè)1之后的0會(huì)全部變成1;

(3)其他位相同;

栗子:

  1.            x = 1011 0000 
  2.          x-11010 1111 
  3. x & (x-1) = 1010 0000 

于是,n&(n-1)這個(gè)操作,可以起到“消除最后一個(gè)1”的功效。

思路:逐步通過n&(n-1),來消除n末尾的1,消除了多少次,就有多少個(gè)1。

偽代碼:

  1. while(n){ 
  2.    result++; 
  3.    n&=(n-1); 
  4.   

分析:這個(gè)方法,n的二進(jìn)制表示有多少個(gè)1,就會(huì)計(jì)算多少次??偟膩碚f,n的長(zhǎng)度是32bit,如果n的值選取完全隨機(jī),平均期望由16個(gè)1構(gòu)成,平均下來16次,節(jié)省一半的計(jì)算量。

三、查表法。

空間換時(shí)間,是算法優(yōu)化中最常見的手段,如果有相對(duì)充裕的內(nèi)存,可以有更快的算法。

思路:一個(gè)uint32的正整數(shù)n,一旦n的值確定,n的二進(jìn)制表示中包含多少個(gè)1也就確定了,理論上無需重新計(jì)算:

  • 1的二進(jìn)制表示中包含1個(gè)1
  • 2的二進(jìn)制表示中包含1個(gè)1
  • 3的二進(jìn)制表示中包含2個(gè)1
  • 58585858的二進(jìn)制表示中包含15個(gè)1
  • ...

提前計(jì)算好結(jié)果數(shù)組:

  1. result[1]=1; 
  2. result[2]=1; 
  3. result[3]=2; 
  4. … 
  5. result[58585858]=15; 
  6. … 

偽代碼:

  1. return result[n]; 

查表法的好處是,時(shí)間復(fù)雜度為O(1),潛在的問題是,需要很大的內(nèi)存。

內(nèi)存分析:

  • 假如被分析的整數(shù)是uint32,打表數(shù)組需要記錄2^32個(gè)正整數(shù)的結(jié)果。
  • n的二進(jìn)制表示最多包含32個(gè)1,存儲(chǔ)結(jié)果的計(jì)數(shù),使用5個(gè)bit即可。
  • 故,共需要內(nèi)存2^32 * 5bit = 2.5GB。

畫外音:5個(gè)bit,能表示00000-11111這32個(gè)數(shù)。

四、二次查表法。

查表法,非??欤徊樵円淮?,但消耗內(nèi)存太大,在工程中幾乎不被使用。

算法設(shè)計(jì),本身是一個(gè)時(shí)間復(fù)雜度與空間復(fù)雜度的折衷,增加計(jì)算次數(shù),往往能夠減少存儲(chǔ)空間。

思路:

(1)把uint32的正整數(shù)n,分解為低16位正整數(shù)n1,和高16正整數(shù)n2;

(2)n1查一次表,其二進(jìn)制表示包含a個(gè)1;

(3)n2查一次表,其二進(jìn)制表示包含b個(gè)1;

(4)則,n的二進(jìn)制表示包含a+b個(gè)1;

偽代碼:

  1. uint16 nn1 = n & 0xFFFF; 
  2. uint16 n2 = (n>>16) & 0xFFFF; 
  3. return  result[n1]+result[n2]; 

問題來了:增加了一倍的計(jì)算量(1次查表變2次查表),內(nèi)存空間是不是對(duì)應(yīng)減少一半呢?

內(nèi)存分析:

  • 被分析的整數(shù)變成uint16,打表數(shù)組需要記錄2^16個(gè)正整數(shù)的結(jié)果。
  • n1和n2的二進(jìn)制表示最多包含16個(gè)1,存儲(chǔ)結(jié)果的計(jì)數(shù),使用4個(gè)bit即可。
  • 故,共需要內(nèi)存2^16 * 4bit = 32KB。

好神奇!!!

計(jì)算量多了1次,內(nèi)存占用量卻由2.5G降到了32K(1萬多倍),是不是很有意思?

五、總結(jié)

數(shù)1,不難;但其思路有優(yōu)化過程,并不簡(jiǎn)單:

(1)位移法,32次計(jì)算;

(2)n&(n-1),能消除一個(gè)1,平均16次計(jì)算;

(3)查表法,1次查表,2.5G內(nèi)存;

(4)二次查表法,2次查表,32K內(nèi)存;

知其然,知其所以然。

思路比結(jié)論重要。

【本文為51CTO專欄作者“58沈劍”原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)聯(lián)系原作者】

戳這里,看該作者更多好文 

 

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2021-12-20 10:39:30

TopK排序代碼

2021-11-02 07:54:40

List分片Java

2024-09-19 18:03:31

2022-12-29 08:46:15

IT采購(gòu)投資

2022-12-07 11:24:51

首席信息官IT

2009-07-03 17:48:24

JSP頁面跳轉(zhuǎn)

2025-04-25 08:55:00

Pod運(yùn)維

2022-09-15 14:05:02

ES開源

2021-08-27 16:26:11

敏感數(shù)據(jù)

2020-07-24 20:45:51

Spark數(shù)據(jù)集函數(shù)

2021-06-23 13:57:13

數(shù)據(jù)泄露網(wǎng)絡(luò)攻擊數(shù)據(jù)安全

2011-04-21 10:08:34

2022-01-10 06:52:59

查詢MySQL字段

2022-11-23 13:46:02

云支出云計(jì)算

2020-04-02 10:45:48

多云云計(jì)算云平臺(tái)

2015-09-10 09:30:54

Java多線程同步

2019-07-31 08:44:27

Session共享Memcache

2025-03-05 09:10:00

session開發(fā)Web

2023-12-27 11:31:27

2020-08-06 13:19:10

IBM多云管理
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)