程序員面試題精選100題:41-50解題報告

程序員面試題精選100題(41)-把數組排成最小的數[算法]  

題目:輸入一個正整數數組,將它們連接起來排成一個數,輸出能排出的所有數字中最小的一個。例如輸入數組{32,  321},則輸出這兩個能排成的最小數字32132。請給出解決問題的算法,並證明該算法。

根據題目的要求,兩個數字m和n排成的數字mn和nm,如果mn<nm,那麼我們應該輸出mn,也就是m應該排在n的前面,也就是m小於n;反之,如果nm<mn,n小於m。如果mn==mn,m等於n。

接下來我們考慮怎麼去拼接數字,即給出數字m和n,怎麼得到數字mn和nm並比較它們的大小。直接用數值去計算不難辦到,但需要考慮到的一個潛在問題是m和n都在int能表達的範圍內,但把它們拼起來的數字mn和nm就不一定能用int表示了。所以我們需要解決大數問題。一個非常直觀的方法就是把數字轉換成字符串。

 

===========================================================================

程序員面試題精選100題(42)-旋轉數組的最小元素[算法]  

題目:把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。輸入一個排好序的數組的一個旋轉,輸出旋轉數組的最小元素。例如數組{3, 4, 5, 1, 2}爲{1, 2, 3, 4, 5}的一個旋轉,該數組的最小值爲1。

分析:遍歷可以獲得最小元素,所以考察的複雜度肯定小於O(n),那基本只有O(logn)了,那就是折半查找了。怎麼利用折半呢?

判斷l-mid是否遞增(a[l]<=a[mid]),如果是那麼結果在右邊,l=mid+1;否則還在左邊,迭代或者遞歸。

終止條件是l=r.

特殊情況a[l]<=a[r],直接返回a[l]。。。

 

擴展:

===========================================================================

程序員面試題精選100題(43)-n個骰子的點數[算法]  

題目:把n個骰子扔在地上,所有骰子朝上一面的點數之和爲S。輸入n,打印出S的所有可能的值出現的概率。

分析:遞推關係:f(n,s)=sum(f(n-1,s-k))*1/6,1<=k<=6

初始f(0,0)=1,f(0,1….6n)=0;0<=s<=6n

結果:f(n,n….6n)

我不知道這個叫不叫動態規劃哦,不過和動態規劃是一個路子。

空間優化:可以使用滾動數組優化爲只用一個數組存儲,沒必要使用n維存儲,s從右向左。

 

直接遞歸會重複計算,也可以使用記憶遞歸避免重複。

===========================================================================

程序員面試題精選100題(44)-數值的整數次方[算法]  

題目:實現函數double Power(double base, int exponent),求base的exponent次方。不需要考慮溢出。

坑不少吶,負數,除零,,,,而且還可以分治二分優化。。。。。

===========================================================================

程序員面試題精選100題(45)-Singleton(C/C++/C#)  

題目:設計一個類,我們只能生成該類的一個實例。

分析:只能生成一個實例的類是實現了Singleton模式的類型。

我們只需要在最開始調用Singleton4_getInstance(可能來自一個線程,也可能來自多個線程)的時候需要加鎖。當實例已經創建之後,我們就不再需要作加鎖操作,從而在後續調用Singleton4_getInstance時性能得到提升。

 

http://blog.csdn.net/nanjunxiao/article/details/8974639

===========================================================================

程序員面試題精選100題(46)-對稱子字符串的最大長度[算法]  

題目:輸入一個字符串,輸出該字符串中對稱的子字符串的最大長度。比如輸入字符串“google”,由於該字符串裏最長的對稱子字符串是“goog”,因此輸出4。

分析:O(n^3)的能想到,O(n^2)的O(n)的沒想到。。。智商拙計

O(n^2)以每個字符爲中心,向兩邊擴展,判斷是否爲迴文,O(n),n箇中心所以複雜度爲O(n^2)。

相對於暴力O(n^3),減少了兩端中間是否迴文的判斷,肯定是迴文的。

O(n)的後綴樹,不會,找個時間看看。。。

===========================================================================

程序員面試題精選100題(47)-數組中出現次數超過一半的數字[算法]  

題目:數組中有一個數字出現的次數超過了數組長度的一半,找出這個數字。

分析:1.hash

2.血拼。。。最後剩下的就是。

===========================================================================

程序員面試題精選100題(48)-二叉樹兩結點的最低共同父結點[數據結構]  

輸入二叉樹中的兩個結點,輸出這兩個結點在數中最低的共同父結點。

第一變種是二叉樹是一種特殊的二叉樹:查找二叉樹。也就是樹是排序過的,位於左子樹上的結點都比父結點小,而位於右子樹的結點都比父結點大。我們只需要從根結點開始和兩個結點進行比較。如果當前結點的值比兩個結點都大,則最低的共同父結點一定在當前結點的左子樹中。如果當前結點的值比兩個結點都小,則最低的共同父結點一定在當前結點的右子樹中。

第二個變種是樹不一定是二叉樹,每個結點都有一個指針指向它的父結點。於是我們可以從任何一個結點出發,得到一個到達樹根結點的單向鏈表。因此這個問題轉換爲兩個單向鏈表的第一個公共結點。我們在本面試題系列的第35討論了這個問題。

現在我們回到這個問題本身。所謂共同的父結點,就是兩個結點都出現在這個結點的子樹中。因此我們可以定義一函數,來判斷一個結點的子樹中是不是包含了另外一個結點。這不是件很難的事,我們可以用遞歸的方法來實現:

這種會重複計算。接着我們來分析一下這個方法的效率。函數HasNode的本質就是遍歷一棵樹,其時間複雜度是O(n)(n是樹中結點的數目)。由於我們根結點開始,要對每個結點調用函數HasNode。因此總的時間複雜度是O(n2)。

我的想法是先序遞歸遍歷,每個節點存儲從根到該節點的路徑,只需遞歸一次,最終找到兩個節點,兩個路徑最後一個相等的即爲結果。但明顯空間使用較多。

答案給出了一種方法,但需要遞歸兩遍來找到兩個節點,同時得到路徑。。。

===========================================================================

程序員面試題精選100題(49)-複雜鏈表的複製[算法]  

 下圖是一個含有5個結點的該類型複雜鏈表。圖中實線箭頭表示m_pNext指針,虛線箭頭表示m_pSibling指針。爲簡單起見,指向NULL的指針沒有畫出。

                  

                

請完成函數ComplexNode* Clone(ComplexNode* pHead),以複製一個複雜鏈表。

 

維護一個hash_map <N,N’>方便定位subing,O(n)複雜度

答案沒看。。。。

===========================================================================

程序員面試題精選100題(50)-樹的子結構[數據結構]  

輸入兩棵二叉樹A和B,判斷樹B是不是A的子結構。

例如,下圖中的兩棵樹A和B,由於A中有一部分子樹的結構和B是一樣的,因此B就是A的子結構。

                1                                                  8
              /   \                                               /   \
             8    7                                            9    2
            /   \
          9    2
               /  \
              4  7

 

遞歸:

Booldigui(Tree* A,Tree* B)

{

         If(NULL == B)

                   Return true;

         If(NULL == A)

                   Return false;

         If(A->data == B->data)

         {

                   Return digui(A->l,B->l)&& digui(A->r,B->r);

}

Else

{

         Return digui(A->l,B)|| digui(A->r,B);

}

}

沒問題吧,不用答案的那種先遞歸找到相同根節點,在遞歸判斷是否相同子樹。。。。兩個遞歸揉到一個遞歸裏了。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章