一道看似簡單的面試題

clipboard.png

前言

使用PHP,給定一個數,判斷這個數是不是二的N次方

這樣看似簡單的一個面試題, 實際牽出了不少基礎知識,本章在爲你們補習基礎知識的狀況下來解答這道題。先亮出答案php

function exponentiation($number)
{
    if ($number < 0) {
        return false;
    }
        
    if (($number & ($number - 1)) == 0) {
        return true;
    } else {
        return false;
    }
}
    
exponentiation (2);
exponentiation (8);
exponentiation (16);
exponentiation (32);
exponentiation (128);

這是查閱後的最最標準的答案,其餘相似經過循環等等答案就略過把。程序員

運算

實際這道面試題考的並不是是算法,而是做爲開發人員的你「底子」夠不夠。
運算符應該是每門語言hello world 後立馬要學習的。運算符分不少種,賦值運算符,比較運算符等等。我想大多自學或者培訓出道的沒有通過系統化學習的童鞋的,對這塊的知識應該很薄弱把。固然賦值、比較什麼的很熟悉,因業務基本逃不過這些。但對位運算符,你真的吃透了嗎?面試

這道題的考點一是位運算符的使用,上面說過了本題考察的並不是算法,而是你對二進制的瞭解,而在php中能操做二進制的運算符 貌似 (個人知識範圍內) 只有位運算符

PHP位運算符 (部分)

本道面試題用到了 & 因此不詳解其餘的運算符,須要更多瞭解請移步官方
http://php.net/manual/zh/lang...算法

運算符 附加信息
& 按位與運算符
^ 按位異或運算符

按位與

按位與以簡單易懂的方式來說就是二進制位不相同的抵消,相同的保留學習

clipboard.png

舉幾個栗子spa

公式 -> 轉爲二進制後的公式 -> 二進制結果 -> 十進制結果
2 & 3 -> 0010 & 0011 -> 0010 = 2
10 & 7 -> 1010 & 0111 -> 0010 = 2
32 & 70 -> 0100000 & 1000110 -> 0000000 = 0

按位異或

按位異或以簡單易懂的方式來說就是二進制位相同的抵消,不相同的保留.net

clipboard.png

舉幾個栗子3d

公式 -> 轉爲二進制後的公式 -> 二進制結果 -> 十進制結果
2 ^ 3 -> 0010 ^ 0011 -> 0001 = 1
10 ^ 7 -> 1010 ^ 0111 -> 1101 = 13
32 ^ 70 -> 0100000 ^ 1000110 -> 1100110 = 102

進制

借用百度百科上的一段話code

二進制是計算技術中普遍採用的一種數制。二進制數據是用0和1兩個數碼來表示的數。它的基數爲2,進位規則是「逢二進一」,借位規則是「借一當二」。

二進制自己就是爲2這個數字而使用的,因此說這道面試題直指二進制的使用是沒錯的。2的n次方則就是blog

n 公式 結果
1 2 2
2 2x2 4
3 2x2x2 8
4 2x2x2x2 16

換算成二進制的表格是

n 公式 結果
1 2 000010
2 2x2 000100
3 2x2x2 001000
4 2x2x2x2 010000

由此看出2的n次方的二進制最高位是1,其他補0,(n&(n-1))==0 而且 n> 0 的狀況下一定是2的n次方,爲何要-1呢?在二進制中每一位必須都不相同&後纔會得出0,上述已經講解了&的運算結果。例如十進制的16

16 & (16 - 1) = 
010000 & (001111) = 0

不要糾結(n&(n-1))==0 這個公式是怎麼來的,做爲程序員,我感受應該把更多時間放到反推上面來,去應證這個公式的正確性。

驗證是不是2的n次方,笨的方法就是一直除2,除到最後等於0則就是2的次方,因此公式如上

補位

若是是2個二進制進行運算時,計算機會統一位數,例如

01
011
<------> 
001
011

計算機會將01自動補一位爲001去方便運算。

正負

在二進制中,第一位爲1的是負數,0是正數。若是沒有補零的狀況下

10000000000
01111111111

雖然計算後也是0,但它並非2的n次方,由於第一組二進制是負數。

補充

由上述題補充的另一道題

給定任意數,計算是2的幾回方?
function power($number){
    if ($number < 0) {
        return false;
    }
    
    if (($number & ($number - 1)) == 0) {
        
        // 數學很差的,就看下面的方法
        // $number = decbin($number);
        // return (mb_strlen($number)-1);
        // 數學能夠的就看下面的方法
        return floor(log($number,2));
    } else {
        return false;
    }
}
  1. 判斷是不是2的n次方
  2. 若是是則將十進制數字轉爲二進制
  3. 計算總長度-1獲取到是2的幾回方,按照0的個數來計算

致謝

感謝你看到這裏,我也是文中提起的沒好好學基礎的一名程序員,但當你看到我這篇文章後,但願你也能夠提起精神,去重溫下基礎,對你將來的職業生涯會起做用的。本章內容純屬本身理解,若有出入,請大佬們監督批評,謝謝🙏

相關文章
相關標籤/搜索