日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

复盘二进制的习题(1)

發(fā)布時間:2023/12/10 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 复盘二进制的习题(1) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

  本文是對近期二進制專題的leetcde習題的復盤。文中的解決思路來源于leetcode的討論,以及一些網(wǎng)頁。
342 判斷一個整數(shù)(32bits)是否是4的次冪。
 寫出4i,i=0,1,2,3,4...的二進制表示,查找規(guī)律。會發(fā)現(xiàn)這些數(shù)的特征是 a 都>0;b 只有一位是1,代碼:n&(n-1)==0;c 1都在奇數(shù)位置,如果從1開始數(shù),代碼:n&(0x55555555)!=0。

191 數(shù)數(shù)一個無符號整數(shù)n的二進制表示中有幾個1。
 方法一:每次判斷最末位置是否為1:n&1==1=>最末位是1;接著n=n>>1,繼續(xù)判斷。
 方法二:每次判斷n的某一個位置,從最末位開始。n&1!=0=>該位是1;接著計算(n&(1<<1)),再繼續(xù)n&(1<<2),如此下午,判斷32個位置。方法一和二思路是相同的,都是通過位移來判斷不同的位置,都需要32次循環(huán),只是一個移動數(shù)字,一個移動掩碼mask。
 方法三:如果數(shù)字n的二進制位只有1位是1,循環(huán)32次太浪費了。n&(n-1) 實際上是把一個數(shù)的最低位的有效1,給去掉了;而且一次還只能去掉一個位置上的1。這樣只要n=(n&(n-1)),n不等于0,就知道1的位數(shù)是加1的。
 思考:如果是有符號的呢?

136 Single Number。給定的數(shù)組中,每個數(shù)都出現(xiàn)了兩次,只有一個數(shù)出現(xiàn)了一次。找到只出現(xiàn)了一次的數(shù)。
 方法:兩個相同的數(shù)異或之后會是0。所有數(shù)字異或之后加和,留下的數(shù)就是要找的數(shù)。

461 Hamming Distance。海明距離是計算兩個int,都多少個位是不同的。
 方法:任意兩個數(shù)異或之后不同的位會變?yōu)?。步驟是:n=(i^j);數(shù)n有幾個1,等同于191。
 
169 Majority Element. 主元素是指在數(shù)組中出現(xiàn)次數(shù)超過n/2的元素。前提假設:數(shù)組不為空;主元素總數(shù)存在。(這題做過,怎么一點印象都沒有)
 方法1:循環(huán)計算nums[i]出現(xiàn)次數(shù)。時間復雜度O(n2)
 方法2:用hashmap,保存每個數(shù)字出現(xiàn)次數(shù)。時間復雜度O(n),空間復雜度O(n)
 方法3:先排序,再找到最長的連續(xù)串。時間復雜度O(nlogn)
 方法4:分治法,數(shù)組一分為2,查找第一部分的主元素A,第二部分的主元素B。如果A的次數(shù)=B的次數(shù),A和B都是候選主元素。如果不同,則選出主元素。時間復雜度O(nlogn)
 方法5:隨機選元素(不甚理解)。平均時間復雜度O(n),最壞是無窮。隨機啊。。。。
 方法6:Moore Voting algorithm。定義候選元素element和次數(shù)count。不斷遍歷nums,如果count=0,element=當前元素,count=1;如果count>0,當前元素=element則count++;否則count–。留下的element一定是主元素。時間復雜度O(n)。這個想法太奇妙了。有點像雙方交戰(zhàn),主元素是一方,其他元素是一方。不斷增加或者減少count。
 方法7:位運算。直接上代碼吧。有點不會描述了。一個int,32位。哪個位置上1的個數(shù)>n/2,那這一位一定是主元素貢獻的。所以只要找到1出現(xiàn)次數(shù)超過n/2的位,其他位置為0,就可以找到主元素。 

public int majorityElement(int[] nums) {int[] bit = new int[32];for (int i = 0; i < nums.length; i++) {for (int j = 0; j < 32; j++) {bit[j] += (nums[i] >> j) & 1;}}int majority = 0;for (int j = 0; j < 32; j++) {bit[j] = bit[j] > (nums.length / 2)? 1 : 0;majority += bit[j] << j;}return majority;}

405 將一個整數(shù)用十六進制表示
 方法:做十進制與十六進制基礎元素的映射。做映射有兩種方式,一種是map,一種是數(shù)組。當key是數(shù)字的時候用數(shù)組還是比較方便的。nums[]={0,1,2,….a,b,…f}。數(shù)組的下標正好是十六進制對應的十進制。

接著十六進制可以用4位二進制表示。每次將num與0x0f做與操作,這樣就能只留下最后四位了。

public String toHex(int num) {if(num==0) return "0";char[] hexadecimalChar = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };String r = "";while (num != 0) {r = hexadecimalChar[num & 0x0f] + r;num >>>= 4;}return r;}

190 給定一個無符號的整數(shù)num,輸出一個整數(shù)out,這個整數(shù)是輸入數(shù)字的二進制的逆轉(zhuǎn)。如果方法要多次調(diào)用,可以怎么優(yōu)化。
 方法一:變量r為最后結(jié)果,從num低位開始,每次處理1位,r<<1+最低位處理的值。循環(huán)32次。 

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)化的方法應該是存儲字節(jié)與結(jié)果的映射關系。
 方法二:可以先看代碼。來自網(wǎng)頁。每4位當做一個整體處理,int32位分為8個部分:abcdefgh。處理順序是:abcdefgh -> efghabcd -> ghefcdab -> hgfedcba。代碼最后兩行是處理:4位內(nèi)部的倒序。
 這思路看到后真是震驚。原來分治法還能這么玩。膜拜啊。
 

public int reverseBits(int n) {n = (n >>> 16) | (n << 16);n = ((n & 0xff00ff00) >>> 8) | ((n & 0x00ff00ff) << 8);n = ((n & 0xf0f0f0f0) >>> 4) | ((n & 0x0f0f0f0f) << 4);n = ((n & 0xcccccccc) >>> 2) | ((n & 0x33333333) << 2);n = ((n & 0xaaaaaaaa) >>> 1) | ((n & 0x55555555) << 1);return n;}

476 Number Complement。一個int的補是指二進制取反。但是高位的0不變。例如5的補是2。因為 5=101 ,取反,010=2。但是一個int有32位,對于5,從第4位開始的0都不算。所以需要知道最高位的1,在哪個位置即可。
  下面是兩種解法。

public int findComplement(int num) {return ~num & (Integer.highestOneBit(num) - 1); }public int findComplement2(int num) {int mask = Integer.MAX_VALUE;while((num & mask) !=0){mask <<=1;}System.out.println(~mask);return ~num & (~mask); }

401 Binary Watch。二進制手表。好酷的手表。這是一個窮舉搜索的問題。
時:8 4 2 1 。每一個選與不選分別用1和0 表示。這樣就形成了一個一個的二進制數(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 判斷一個數(shù)是否是2的平方。2的平方的特征是:a 大于0;2 只有一個1。

public boolean isPowerOfTwo(int n) {return n>0 && (n&(n-1))==0;}

389 Find the Difference。輸入兩個字符串s、t。t是s中所有字母隨機排列后組成的字符串,但是t中有一個字符在s中沒有出現(xiàn)。找出在t中沒有出現(xiàn)的那個字符。
思路一:用map。遍歷s中每個字符的出現(xiàn)次數(shù),保存在map中。接著遍歷t中的字符串,將map[key]value值減1。如果在map的key值不存在或者說map[key]的value <=0 ,那這個字符一定不在s中出現(xiàn)。
思路2:位操作。用異或可以將相同的字符抵消。s和t兩個字符串做異或,留下的就是沒在s中出現(xiàn)的字符。

public char findTheDifference2(String s, String t) {char ch =0;for(int i=0;i<s.length();i++){ch ^= s.charAt(i);ch ^= t.charAt(i);}ch ^= t.charAt(t.length()-1);return ch; }

268 Missing Number。給一個包含n個不同數(shù)值的數(shù)組nums,數(shù)組本應該是0,1,2,…n這樣的數(shù)字,但是丟了一個數(shù)字。返回丟失的數(shù)字。例如輸入 nums = [0, 1, 3] 返回2。
思路:這個題目與上一提很相似。389是查找多出的字符,268是查找丟失的數(shù)字。都是從兩個可比較的對象中,查找出多的或者少的部分。

public int missingNumber(int[] nums) {int xor = 0,i=0;for(i=0;i<nums.length;i++){xor = xor^i^nums[i];}return xor ^= i;}

371 Sum of Two Integers。不用+ - 操作求兩個數(shù)的和。這個解法就是比較神奇了。處理兩個數(shù)相同的部分;處理兩個數(shù)相異的部分。兩個數(shù)相同的部分加和的時候還要向前進一,和我們手動計算和相似。

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)址
可能會有落下的網(wǎng)址,未列出。謝謝作者們。

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的复盘二进制的习题(1)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。