程序員面試題精選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);
}
}
沒問題吧,不用答案的那種先遞歸找到相同根節點,在遞歸判斷是否相同子樹。。。。兩個遞歸揉到一個遞歸裏了。。。