關於微軟面試100題系列中兩道題目的個人解法

2021-07-15 10:47:54 字數 3598 閱讀 8110

最近為了準備找工作,刷了july大神整理的微軟100題系列,中間有兩道題目在原博主文中並沒有給出很好地解決方案,在此文中給出個人的解法,希望拋磚引玉,請求大神給予指導。

第一道是30題,原題描述如下:

題目:輸入乙個整數 n,求從 1到 n這 n個整數的十進位制表示中 1出現的次數。例如輸入 12 ,從 1到 12 這些整數中包含 1 的數字有 1,10 ,11和 12 ,1一共出現了 5次。

分析:這是一道廣為流傳的 google面試題。

這道題目很明顯是可以用遞迴實現的。考慮三個數字:

321,111。

1.對於321,首先考慮個位數:個位數大於等於1,在0~9中1只能出現1次,因此這裡各位出現1個1;接著考慮十位,十位大於1,可以得知在0~20中只能是0~9中出現1次、10~19中出現11次,也就是一共20次,那麼考慮當十位數不是2,而是3,或者4時,增加的也僅僅是1個或者兩個1.也就是說在此情況下(注意此時僅考慮當前位,不考慮其他位,也就是整十整百之類的數)1出現的次數可以總結為countn(n,k)=10^(k-1)+n*countn(10,k-1);其中n是當前位的值,k則是其倍率(十位時k=2,百位時k=3).同樣的道理可以用在百位上,將所有位出現的加在一起即可得到最終結果。

2.對於111,個位採用同樣的方式進行判斷,但是十位時我們發現這一位等於1,那麼我們首先需要將低於當前位的值記錄下,因為最後的結果中需要加上它,以此為例,我們需要記住最終結果需要加上1,同時由於即便當前位的低位全部為0我們也需要加1,也就是說最終結果的組成部分需要+2,(10,11中各自由於十位的1而加1,注意此時我們僅僅計算當前位的,比當前位低的已經計算完成),然後我們對當前位(在此是1)所代表的值(10)減去1,然後對其遞迴呼叫計數函式。在此例中是計算9的計數問題。然後我們將所有結果疊加即可得到最後結果。

我發現數字無非這兩種情況,因此總可以遞迴實現其求解。演算法詳情見下文。

//30.在從1到n的正數中1出現的次數

#includeint countn(int n,int k)

if (n > 1)

else if (n == 1)

return -1;

else

return 0;

}int count1(int num)

else

} return count;

}int main()

第二道題目是32題,原題描述如下:

有兩個序列a,b,大小都為n,序列元素的值任意整數,無序;

要求:通過交換a,b中的元素,使[序列a元素的和]與[序列b元素的和]之間的差最小。

例如: 

var a=[100,99,98,1,2, 3];

var b=[1, 2, 3, 4,5,40];

據說這一題是微軟的面試題。

當我第一次看到這個題目,最簡單的思路就是直接合在一起排序,然後逐個抽取數字分配到兩個陣列中。這當然是大錯特錯的。奈何本人比較愚笨,只能檢視答案。然而答案給出的**也是不正確的。網上所傳的演算法我看到的目前有三種,前兩種演算法可以參照一下原博主july大神的博文但是可以很負責任地告訴大家這兩種方法都是錯的,從大神貼出來的答案也是可以很明顯看出的。第三種方法鏈結在此

一方面博主說的我也不是特別懂,另一方面本人比較懶,不喜歡看別人寫的特別是用其他語言寫的**,就索性自己琢磨。事先宣告我不清楚自己的演算法是不是和其他人一樣,也是不是最優,但是我測試的幾組不同情況下的確實滿足。

我的思路是:首先將兩組數組合為一組然後進行排序(這裡使用快排)。隨後我將整個陣列分成前後長度相等的兩部分,以原題為例:

合併排序後:1,1,2,2,3,3,4,5,40,98,99,100;

拆分:a1:1,1,2,2,3,3

a2:4,5,40,98,99,100

然後計算兩個陣列的和的差值(334)。然後我們從陣列頭開始,若交換1,4,判斷差值會不會減少(絕對值)。如果減少就交換,否則指標後移直到陣列尾。隨後我們可以得到這樣兩個陣列:

a1:4,5,40,98,3,3

a2:1,1,2,2,99,100

我們將兩個陣列重新排序,重複進行比較操作直到遇到當所有元素都沒有發生交換或者某次交換後差值為0時返回。

我們得到的最後結果是:

a1:3,3,4,5,40,100;

a2:1,1,2,2,98,99.

差值:48.

至於是不是最優,原諒本人比較愚笨,暫時沒看出來。。。。。。

具體**實現如下:

//32.有兩個序列a,b,大小為n,序列元素的值為任意整數,無序;要求通過交換a,b中的元素,使序列a的和與序列b的和之間的差最小。

//writer&idea:jayleeustc

#includevoid swap(int&a,int&b)

void quicksort(int* a,int left,int right)

a[i] = val;

quicksort(a, left, i - 1);

quicksort(a, i+1, right); }}

int sum(int*a, int len)

return temp;

}void arrange(int a1,int a2,int len)//合併序列

quicksort(a3, 0, 2*len-1);//排序

for (int i = 0; i < len; ++i)//排序後的拆分序列

bool sign = true;//符號識別符號,正數為true,負數為false。

bool ifswap = false;

int prev = sum(a2, len) - sum(a1, len);//儲存上一次運算的差值。

while (true)

else if (sumch < 0 && abs(sumch) < prev)//交換當前項後和的差值變小且變號

else if (sumch == 0||sumch==prev)//找到最佳值或交換對總和無變化

return;

}else if (!sign)

else if (sumch < 0 && abs(sumch < prev))

else if (sumch == 0 || sumch == prev)//找到最佳值或交換對總和無變化

return;

}} if (!ifswap)

return;

//重新排序

quicksort(a1, 0, len - 1);

quicksort(a2, 0, len - 1);

ifswap = false; }}

int main();

int a2[4] = ;

int len=sizeof(a1)/sizeof(a1[0]);

arrange(a1, a2, len);

for (int i = 0; i < len; ++i)

std::cout << a1[i] << " ";

std::cout << std::endl;

for (int i = 0; i < len; ++i)

std::cout << a2[i] << " ";

std::cout << std::endl;

std::cout <<"the final result is:"<

兩道面試演算法題

最近面試 兩道演算法題 說難不難 要寫全對也不容易 很慚愧 我沒有一次寫對 第一道 無序int陣列 找到中位數 void swap int a,int b int get kth number vector num,int k,int start,int end 一次劃分結束 index i if ...

CVTE 面試的兩道演算法題

下了班立馬趕往深圳北站,下著大雨又坐過了站,著急地跑向對面的站牌,匆忙間搞得滿頭大汗。好不容易坐上了高鐵,休息片刻,終於有時間整理一下前兩天面試cvte 時遇到的兩道演算法題。1.在陣列中尋找和為固定值的兩個數字 這道題目是一面的時候乙個女面試給出的最後乙個面試問題。題目的大概意思如上,資料不一定有...

微軟等面試100題系列 45 2

2.乙個整數陣列,長度為n,將其分為m份,使各份的和相等,求m的最大值 比如 可以分成 m 1 m 2m 3 所以m的最大值為3 package com.interview.algorithm public class leveragesum 可以分成 m 1 m 2m 3 所以m的最大值為3 pu...