有時候面試官每每會問咱們一些簡單,但又刁難的問題,主要是看看你對問題的處理思路。若是你沒接觸過這些問題,可能一時之間還真不知道怎麼處理才比較好,這種題更重要的是一種思惟的散發吧,今天就來分享幾道題面試中遇到的算法題(固然,不是我本身遇到過,是別人遇到過,我挑選出來的)面試
題目描述:求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等關鍵字及條件判斷語句(A?B:C)。
我去,求和竟然不讓用乘除法,也不許咱們用循環,若是單獨這兩個限制的話還好,咱們還能夠用地遞歸,例如:算法
int f(int n){ if(n == 0){ return n; }else{ return f(n-1) + n; } }
而後 if, else, case 等各類關鍵字也不給用,想着那我用三元運算符(A?B:C),而後這種具備判斷語句的三元運算符也不給用,我去,這也太刁難了吧(固然,大佬直接秒殺的能夠飄過)。函數
這道題確定是必須用遞歸來解決的,而這遞歸的核心就是須要判斷一下遞歸條件是否結束了,然而題目不許咱們使用條件判斷語句。那咱們該怎麼辦呢?你們能夠散發思惟想一下哦。spa
其實咱們能夠下面這樣的語句來代替 A?B:C 這樣具備判斷能力的三元運算符code
n != 0 && (f(n-1) + n) != 0;
這個 && 邏輯判斷符的做用就是:若是 n != 0 成立的話,那麼邏輯判斷符後面的判斷語句 (f(n-1) + n ) != 0 也會執行,若是 n != 0 不成立的話,那麼後面的判斷語句 ((f(n-1) + n)) != 0 就不會執行,經過這種方法,就能夠達到咱們遞歸結束條件判斷的目的了。blog
這裏說明一下,(f(n-1) + n) != 0 這條判斷語句是沒有任意其餘含義的,咱們的目的是爲了執行 f(n-1)+n,之因此加上個 != 0 的判斷,是由於邏輯判斷符號 && 只支持 boolean 類型,不支持 int 類型。
最後的代碼以下遞歸
public int f(int n) { int sum = n; boolean t = (n != 0) && (sum += f(n - 1))!= 0; return sum; }
若是你作過這種類型的題,可能就會以爲很簡單了,若是沒作過,可能就須要思考一下,不過,日後你就能夠直接秒殺了。ip
題目描述:寫一個函數,求兩個整數之和,要求在函數體內不得使用+、-、*、/四則運算符號。
我去,求和不許加減乘除!面試官,能不能別這麼任性,好好的加減乘除竟然不給用。it
不過我相信你們第一時間都能想到用位運算來解決,可能在大學期間學過電路相關知識的一下就能把代碼寫出來了,不過有些人也能多是一個位一個位來處理的。例如我先處理第一個位(這裏指的是二進制位哈),看看有沒進位,而後處理第二個位,若是第一個位有進位就加到第二個位來,而後處理第三個位.....class
若是你是這種方法處理的,那麼恭喜你,看完這道題你能有所收穫。實際上上面那種解法也能夠,只是太複雜了,可能各類判斷。其實這道題能夠這樣解:這裏爲了方便講解,我先給出代碼,再給出具體的講解,你看完代碼再來看講解可能更好理解
public int Add(int num1,int num2) { int tmp = 0; while(num1 != 0){ tmp = num1 ^ num2; num1 = (num1 & num2) << 1; num2 = tmp; } return num2; }
你們想一個問題,若是咱們把兩個數進行異或,例如num1 = 101, num2 = 001,作異或運算:tmp = num1 ^ num2,結果是 tmp = 100。那麼此時獲得的結果 tmp 其實就是兩個數(num1,num2)各個二進制位上相加,不算進位的結果。而 num1 = (num1 & num2) << 1 的結果就是兩個數相加時那些須要進位的二進制位。例如 (101 & 001)<< 1 = 010,那麼兩個數第一位相加須要進位,咱們須要把進的那一位最後加到第二位上去。
好像有點繞,,你們能夠動手試一下哈,說白就是 a + b = a ^ b + (a & b) << 1。
代碼中,若是 num1 == 0 的話,表明沒有進位了,此時就能夠退出循環了。
對於不多用位運算的人來講可能有點懵,那麼我建議能夠多看幾遍,而後一遍動手模擬哈。之後遇到這種題就能夠直接秒殺了。
在這裏我先聲明一下,案例3 也不算一道刁難題,只是我來考考大家而已,你們看到題目以後能夠本身想一下哈,看了答案不能打我哈。
題目描述:實現兩個整數的相乘,不能使用乘法運算符和循環
各位老哥能夠想一下哈。
這道題可能不少人都想到用遞歸了,好像我說的大部分算法題,都會用到遞歸,因此說你不懂遞歸的話,看個人公衆號就好了,不懂也得變懂了是否是。代碼以下:
int mul(int a, int b){ if (a == 0 || b == 0) return 0; if (b == 1) return a; if (a == 1) return b; return a + mul(a, b - 1); } int mult(int a,int b){ // 這裏咱們取 b 的絕對值 int sum = mul(a, abs(b)); return (b<0)?(-sum):sum; }
你是否是這樣作的呢?其實,咱們還有更好的方法哦,以下
我去,不能使用乘法,又沒說不能使用除法,那我用除法來代替乘法就得了,例如 a 乘以 b 就至關於 a 除以 b 分之一。代碼以下:
int mult2 (int a,int b){ return b != 0 ? (int)(a / (1.0 / b) + 0.99 ): 0; }
這裏須要 int 進行轉化類型,而且除法可能會致使後面尾數的丟失,因此我補了個 0.99。注意,進行 int 類型轉化時,不是四捨五入的哈,二手小於 1 就行當作 0 處理。固然,我這裏用的是 Java 語言,其餘語言本身看狀況處理。
今天的幾道題,更多的是一種投機取巧吧,不過看你看到一到陌生的題目時,你會如何處理,點子多很少,這個仍是挺重要滴,而多看一些點子,慢慢着你的點子也會變多了。