1問題定義
加入數組arr中數據是:4,0,1,0,2,3,那么第三小的元素是1,問怎么樣快速的求出這個第k小的數。
2.解決方案
解法一:
利用STL中快速排序把數組進行排序,然后數組下標是k-1的就是我們要求的第k小的元素了,這種情況的時間復雜度接近於O(n*logn)。但是回頭想一想這個算法是把數組進行了全排序,而我們只是要找到數組中第k小的數,這顯然是“殺豬用了牛刀”。當然了時間復雜度較高也是正常的。
解法二:
想一想快速排序的思想:將數組中某一個元素m作為划分依據(我們假設為第一個元素,即m = arr[0]),遍歷一遍數組,使得數組的格局變成這樣的三個部分:(1)m前面的元素 (2)m (3)m后面的元素。其中m前面的元素小於m,m后面的元素大於m,這樣找第k小的數正好可以借鑒這個思想,即:
1、若m前面的元素個數大於k,則第k小的數一定在m前面的元素中,這時我們只需要繼續在m前面的元素中搜索第k小的數;
2、若m前面的元素個數小於k,則第k小的數一定在m后面的元素中,這是我們只需要繼續在m后面的元素中搜索第k-s小的數,其中s是m前面的元素個數。
下面給出代碼:(在vc6.0下測試)
1 #include <iostream.h> 2 3 #define MAX_SIZE 100 4 5 int Biger[MAX_SIZE]; 6 int Smaller[MAX_SIZE]; 7 8 int Select_kth_Small(int arr[],int n,int k) 9 { 10 if(n == 1) 11 return arr[0]; 12 int b = 0,s = 0,t = arr[0],temp_n,temp_k; 13 int temp[MAX_SIZE]; 14 for(int i = 1 ; i < n ; i++)//遍歷集合 15 { 16 if(arr[i] > t) 17 Biger[b++] = arr[i]; //如果當前元素比t大,就將當前元素加入Biger[] 18 else 19 Smaller[s++] = arr[i];//反之就加入到Smaller,這里沒有考慮set[0] 20 } 21 if(b == 0) 22 { 23 Biger[b++] = t;//if...else主要是為了防止t大於或小於其他所有元素的情況 24 } 25 else 26 { 27 Smaller[s++] = t; 28 } 29 //如果Smaller集合中的元素個數大於K,說明第K小的元素必在其中 30 //否則一定在Biger中,且應該是Biger集合中第k-r小的元素 31 //更新相應的變量 32 if(s >= k) 33 { 34 temp_n = s; 35 temp_k = k; 36 for(i=0;i<temp_n;i++) 37 { 38 temp[i] = Smaller[i]; 39 } 40 } 41 else 42 { 43 temp_n = b; 44 temp_k = k-s; 45 for(i=0;i<temp_n;i++) 46 { 47 temp[i]=Biger[i]; 48 } 49 } 50 return Select_kth_Small(temp,temp_n,temp_k); 51 } 52 53 int main() 54 { 55 int arr[]={4,0,1,0,2,3}; 56 int ans = Select_kth_Small(arr,6,3); 57 cout<<"在數組arr[]={4,0,1,0,2,3}中,第3小的數是:"<<ans<<endl; 58 return 0; 59 }
這個代碼多用了較多的輔助空間,為的是不改變原來的數組的元素的順序。不知道這個代碼有什么漏洞沒有,大家幫幫找找。謝謝嘍……
學習中的一點總結,歡迎拍磚哦^^