Reverse bits of a given 32 bits unsigned integer. For example, given input 43261596 (represented in binary as 00000010100101000001111010011100), return 964176192 (represented in binary as 00111001011110000010100101000000). Follow up: If this function is called many times, how would you optimize it?
這裏涉及了十進制和二進制之間轉化這個知識點。在數學中,咱們都是採用十進制進行計算,通俗說就是逢十進一。可是計算機沒有那麼多類型的信號來對應是十進制數中的十個數字,所以採用了二進制來進行計算。面試
二進制,也就是所謂的逢二進一,每一位上只有兩個數字,分別是0和1。每個十進制都有一個惟一的二進制數做爲對應。咱們先來看一下十進制數的計算,好比945
等價於9*100+4*10+5*1
,也就是9*10^2 + 4*10^1 + 5*10^0
。同理咱們知道,二進制數011
表明0*2^2 + 1*2^1 + 1*2^0
也就是十進制的3
。這樣,咱們知道如何將二進制數轉化爲十進制數。緩存
那麼計算機是怎麼進行計算的呢?計算機首先將十進制數轉化爲二進制數,再將二進制數根據需求進行計算。假設計算機須要計算3+6
,那麼轉化爲二進制就是11+110
,那麼計算機的計算流程以下。微信
1.對齊 在左側補零位使的兩個數字位數相同,所以就是011+110
2.逢二進一 相似於十進制數的逢十進一,所以計算的結果爲1001
,轉化爲十進制數就是9
基於二進制的位計算上,除去加減乘除,計算機還定義了一些其餘的位運算符this
>>
將二進制數右移,左邊根據數字的正負形補0或者補1,正數補0,負數補1。
<<
將二進制數左移,右邊補0
>>>
將二進制數右移,左邊補0
在這些知識的基礎上,咱們再來看這道題目。spa
將比特位逆轉過來也就是將十進制數轉化爲二進制數,再從右往左得到每一位上的值,再將這個值添加至結果值中。設計
public int reverseBits(int n) { //得到最後一位的值 int mask = 1; int result = 0; for(int i=0 ; i<32 ; i++){ result <<= 1; result |= (n & mask); n >>= 1; } return result; }
爲了將比特位逆轉,意味着咱們至少須要32次循環才能將整個遍歷完成。那麼若是這個逆轉比特位方法會被調用屢次的話,咱們能夠使用一個Map來緩存已經遍歷過的狀況。
可是,32位的重複值每每不多,所以咱們能夠將整數分解爲多個片斷存入緩存中,只要遇到重複的片斷,就能夠將已經獲得的結果返回給調用方。根據分治思想,逆轉32個比特位等價於分別將每8個比特位進行逆轉。所以咱們能夠將長度爲32的unsigned int拆解成4個長度爲8的byte。每8個byte對應的值能夠做爲片斷存在緩存中,只要遇到重複的片斷,就能夠直接返回。code
Map<Byte, Integer> cache = new HashMap<Byte, Integer>(); public int reverseBits2(int n){ byte[] bytes = new byte[4]; for(int i = 0 ; i<4 ; i++){ // 得到8位並轉換爲1個byte bytes[i] = (byte) ((n>>>(i*8)) & 0xff); } int result = 0; for(int i = 0 ; i<4 ; i++){ result += reverseByte(bytes[i]); if(i<3) result<<=8; } return result; } public int reverseByte(byte b){ Integer value = cache.get(b); if(value != null) return value; value = 0; for(int i = 0 ; i<8 ; i++){ value += ((b>>>i) & 1); if(i<7) value <<= 1; } cache.put(b, value); return value; }
想要了解更多開發技術,面試教程以及互聯網公司內推,歡迎關注個人微信公衆號!將會不按期的發放福利哦~教程