秋招相關面試題總結(二)

算法

1、給定一個整數n,找出連續整數相加爲該數的情況有多少?

設等差數列:

an=a+(n-1)*d (這裏首項爲a,公差d=1,第n項爲an,前n項和爲sn)

a1=a

an=a+n-1

sn=(a1+an)n/2=(2a-1+n)*n/2

再回到這個編程上來:

我們的輸入數據其實就是sn,需要找到以a開始的n個連續的遞增數列使得和爲sn。

這裏我們可以用循環來判定,給定一個n,sn已知,就可以求出a,如果a爲正整數那麼就可以找到等差數列的首項,加上n給定,d=1,那麼就可以寫出這個和式子。

進一步優化提高程序效率:這裏的n無須一直從2開始枚舉下去,可以由sn=(2a-1+n)*n/2,所以a=sn/n-n/2+1/2,該式子爲遞減函數,n越大,a越小,而a最小爲1,故另a=1時可確定n的最大範圍。

令a=1,得二元一次方程(1/2+n/2)*n=sn,即n^2+n-2*sn=0,可得方程兩個根中取較大的根n=0.5*(-1+sqrt(1+8*sn)),從而確定n的最大枚舉範圍。

2.螺絲和螺母配對

Kmeans++算法

Kmeans++算法是爲了改進Kmeans算法中的初始值選取不當導致效果變差的問題

K-means++算法:

起步

由於 K-means 算法的分類結果會受到初始點的選取而有所區別,因此有提出這種算法的改進: K-means++ 。

算法步驟

其實這個算法也只是對初始點的選擇有改進而已,其他步驟都一樣。初始質心選取的基本思路就是,初始的聚類中心之間的相互距離要儘可能的遠。

算法描述如下:

  • 步驟一:隨機選取一個樣本作爲第一個聚類中心 c1;
  • 步驟二:
    • 計算每個樣本與當前已有類聚中心最短距離(即與最近一個聚類中心的距離),用 D(x)表示;
    • 這個值越大,表示被選取作爲聚類中心的概率較大;
    • 最後,用輪盤法選出下一個聚類中心;
  • 步驟三:重複步驟二,知道選出 k 個聚類中心。

選出初始點後,就繼續使用標準的 k-means 算法了。

效率

K-means++ 能顯著的改善分類結果的最終誤差。

儘管計算初始點時花費了額外的時間,但是在迭代過程中,k-mean 本身能快速收斂,因此算法實際上降低了計算時間。

網上有人使用真實和合成的數據集測試了他們的方法,速度通常提高了 2 倍,對於某些數據集,誤差提高了近 1000 倍。

下面結合一個簡單的例子說明K-means++是如何選取初始聚類中心的。

數據集中共有8個樣本,分佈以及對應序號如下圖所示:

假設經過圖2的步驟一後6號點被選擇爲第一個初始聚類中心,

那在進行步驟二時每個樣本的D(x)和被選擇爲第二個聚類中心的概率如下表所示:

其中的P(x)就是每個樣本被選爲下一個聚類中心的概率。

最後一行的Sum是概率P(x)的累加和,用於輪盤法選擇出第二個聚類中心。

方法是隨機產生出一個0~1之間的隨機數,判斷它屬於哪個區間,那麼該區間對應的序號就是被選擇出來的第二個聚類中心了。

例如1號點的區間爲[0,0.2),2號點的區間爲[0.2, 0.525)。

從上表可以直觀的看到第二個初始聚類中心是1號,2號,3號,4號中的一個的概率爲0.9。

而這4個點正好是離第一個初始聚類中心6號點較遠的四個點。

這也驗證了K-means的改進思想:即離當前已有聚類中心較遠的點有更大的概率被選爲下一個聚類中心。

可以看到,該例的K值取2是比較合適的。當K值大於2時,每個樣本會有多個距離,需要取最小的那個距離作爲D(x)。

KMeans的改進(三角不等式)