复盘二进制的习题(1)
本文是對近期二進(jìn)制專題的leetcde習(xí)題的復(fù)盤。文中的解決思路來源于leetcode的討論,以及一些網(wǎng)頁。
342 判斷一個(gè)整數(shù)(32bits)是否是4的次冪。
寫出4i,i=0,1,2,3,4...的二進(jìn)制表示,查找規(guī)律。會(huì)發(fā)現(xiàn)這些數(shù)的特征是 a 都>0;b 只有一位是1,代碼:n&(n-1)==0;c 1都在奇數(shù)位置,如果從1開始數(shù),代碼:n&(0x55555555)!=0。
191 數(shù)數(shù)一個(gè)無符號整數(shù)n的二進(jìn)制表示中有幾個(gè)1。
方法一:每次判斷最末位置是否為1:n&1==1=>最末位是1;接著n=n>>1,繼續(xù)判斷。
方法二:每次判斷n的某一個(gè)位置,從最末位開始。n&1!=0=>該位是1;接著計(jì)算(n&(1<<1)),再繼續(xù)n&(1<<2),如此下午,判斷32個(gè)位置。方法一和二思路是相同的,都是通過位移來判斷不同的位置,都需要32次循環(huán),只是一個(gè)移動(dòng)數(shù)字,一個(gè)移動(dòng)掩碼mask。
方法三:如果數(shù)字n的二進(jìn)制位只有1位是1,循環(huán)32次太浪費(fèi)了。n&(n-1) 實(shí)際上是把一個(gè)數(shù)的最低位的有效1,給去掉了;而且一次還只能去掉一個(gè)位置上的1。這樣只要n=(n&(n-1)),n不等于0,就知道1的位數(shù)是加1的。
思考:如果是有符號的呢?
136 Single Number。給定的數(shù)組中,每個(gè)數(shù)都出現(xiàn)了兩次,只有一個(gè)數(shù)出現(xiàn)了一次。找到只出現(xiàn)了一次的數(shù)。
方法:兩個(gè)相同的數(shù)異或之后會(huì)是0。所有數(shù)字異或之后加和,留下的數(shù)就是要找的數(shù)。
461 Hamming Distance。海明距離是計(jì)算兩個(gè)int,都多少個(gè)位是不同的。
方法:任意兩個(gè)數(shù)異或之后不同的位會(huì)變?yōu)?。步驟是:n=(i^j);數(shù)n有幾個(gè)1,等同于191。
169 Majority Element. 主元素是指在數(shù)組中出現(xiàn)次數(shù)超過n/2的元素。前提假設(shè):數(shù)組不為空;主元素總數(shù)存在。(這題做過,怎么一點(diǎn)印象都沒有)
方法1:循環(huán)計(jì)算nums[i]出現(xiàn)次數(shù)。時(shí)間復(fù)雜度O(n2)。
方法2:用hashmap,保存每個(gè)數(shù)字出現(xiàn)次數(shù)。時(shí)間復(fù)雜度O(n),空間復(fù)雜度O(n)。
方法3:先排序,再找到最長的連續(xù)串。時(shí)間復(fù)雜度O(nlogn)。
方法4:分治法,數(shù)組一分為2,查找第一部分的主元素A,第二部分的主元素B。如果A的次數(shù)=B的次數(shù),A和B都是候選主元素。如果不同,則選出主元素。時(shí)間復(fù)雜度O(nlogn)。
方法5:隨機(jī)選元素(不甚理解)。平均時(shí)間復(fù)雜度O(n),最壞是無窮。隨機(jī)啊。。。。
方法6:Moore Voting algorithm。定義候選元素element和次數(shù)count。不斷遍歷nums,如果count=0,element=當(dāng)前元素,count=1;如果count>0,當(dāng)前元素=element則count++;否則count–。留下的element一定是主元素。時(shí)間復(fù)雜度O(n)。這個(gè)想法太奇妙了。有點(diǎn)像雙方交戰(zhàn),主元素是一方,其他元素是一方。不斷增加或者減少count。
方法7:位運(yùn)算。直接上代碼吧。有點(diǎn)不會(huì)描述了。一個(gè)int,32位。哪個(gè)位置上1的個(gè)數(shù)>n/2,那這一位一定是主元素貢獻(xiàn)的。所以只要找到1出現(xiàn)次數(shù)超過n/2的位,其他位置為0,就可以找到主元素。
405 將一個(gè)整數(shù)用十六進(jìn)制表示
方法:做十進(jìn)制與十六進(jìn)制基礎(chǔ)元素的映射。做映射有兩種方式,一種是map,一種是數(shù)組。當(dāng)key是數(shù)字的時(shí)候用數(shù)組還是比較方便的。nums[]={0,1,2,….a,b,…f}。數(shù)組的下標(biāo)正好是十六進(jìn)制對應(yīng)的十進(jìn)制。
接著十六進(jìn)制可以用4位二進(jìn)制表示。每次將num與0x0f做與操作,這樣就能只留下最后四位了。
190 給定一個(gè)無符號的整數(shù)num,輸出一個(gè)整數(shù)out,這個(gè)整數(shù)是輸入數(shù)字的二進(jìn)制的逆轉(zhuǎn)。如果方法要多次調(diào)用,可以怎么優(yōu)化。
方法一:變量r為最后結(jié)果,從num低位開始,每次處理1位,r<<1+最低位處理的值。循環(huán)32次?!?/p>
public int reverseBits(int n) {int result = 0;for (int i = 0; i < 32; i++) {result <<= 1;result += n&1;n >>>=1;}return result;}
多次調(diào)用優(yōu)化的方法應(yīng)該是存儲字節(jié)與結(jié)果的映射關(guān)系。
方法二:可以先看代碼。來自網(wǎng)頁。每4位當(dāng)做一個(gè)整體處理,int32位分為8個(gè)部分:abcdefgh。處理順序是:abcdefgh -> efghabcd -> ghefcdab -> hgfedcba。代碼最后兩行是處理:4位內(nèi)部的倒序。
這思路看到后真是震驚。原來分治法還能這么玩。膜拜啊。
476 Number Complement。一個(gè)int的補(bǔ)是指二進(jìn)制取反。但是高位的0不變。例如5的補(bǔ)是2。因?yàn)?5=101 ,取反,010=2。但是一個(gè)int有32位,對于5,從第4位開始的0都不算。所以需要知道最高位的1,在哪個(gè)位置即可。
下面是兩種解法。
401 Binary Watch。二進(jìn)制手表。好酷的手表。這是一個(gè)窮舉搜索的問題。
時(shí):8 4 2 1 。每一個(gè)選與不選分別用1和0 表示。這樣就形成了一個(gè)一個(gè)的二進(jìn)制數(shù)。如果說時(shí)鐘只有一個(gè)燈亮,那么選擇可能有:
時(shí):8 4 2 1
f1: 0 0 0 1
f2: 0 0 1 0
f3: 0 1 0 0
f4: 1 0 0 0
231 判斷一個(gè)數(shù)是否是2的平方。2的平方的特征是:a 大于0;2 只有一個(gè)1。
public boolean isPowerOfTwo(int n) {return n>0 && (n&(n-1))==0;}389 Find the Difference。輸入兩個(gè)字符串s、t。t是s中所有字母隨機(jī)排列后組成的字符串,但是t中有一個(gè)字符在s中沒有出現(xiàn)。找出在t中沒有出現(xiàn)的那個(gè)字符。
思路一:用map。遍歷s中每個(gè)字符的出現(xiàn)次數(shù),保存在map中。接著遍歷t中的字符串,將map[key]value值減1。如果在map的key值不存在或者說map[key]的value <=0 ,那這個(gè)字符一定不在s中出現(xiàn)。
思路2:位操作。用異或可以將相同的字符抵消。s和t兩個(gè)字符串做異或,留下的就是沒在s中出現(xiàn)的字符。
268 Missing Number。給一個(gè)包含n個(gè)不同數(shù)值的數(shù)組nums,數(shù)組本應(yīng)該是0,1,2,…n這樣的數(shù)字,但是丟了一個(gè)數(shù)字。返回丟失的數(shù)字。例如輸入 nums = [0, 1, 3] 返回2。
思路:這個(gè)題目與上一提很相似。389是查找多出的字符,268是查找丟失的數(shù)字。都是從兩個(gè)可比較的對象中,查找出多的或者少的部分。
371 Sum of Two Integers。不用+ - 操作求兩個(gè)數(shù)的和。這個(gè)解法就是比較神奇了。處理兩個(gè)數(shù)相同的部分;處理兩個(gè)數(shù)相異的部分。兩個(gè)數(shù)相同的部分加和的時(shí)候還要向前進(jìn)一,和我們手動(dòng)計(jì)算和相似。
public int getSum(int a, int b) {return b == 0 ? a : getSum(a ^ b, (a & b) << 1); }參考資料
1 bit-manipulation
2 網(wǎng)址
3 網(wǎng)址
可能會(huì)有落下的網(wǎng)址,未列出。謝謝作者們。
總結(jié)
以上是生活随笔為你收集整理的复盘二进制的习题(1)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android通用流行框架大全
- 下一篇: MOSSE跟踪算法源码解析