/** * 問題:從一個由n個不同的數組構成的集合中選擇其第i個順序統計量的問題 * 解決:採用類似快速排序的思想即對輸入數組進行遞迴劃分,不同之處是,快速排序會遞迴處理劃分的兩邊, * 而此方法只處理劃分的一邊。 * 最壞時間複雜度為:O(n^2),平均啟動並執行時間複雜度為O(n) */public class RandomizedSort {/** * 對arr進行遞迴劃分,每次劃分判斷主元元素是否為要找的順序統計量,如果不是,判斷要找的順序統計量在那一個子數組,然後再進行劃分 * @param arr 數組 * @param p 開始下標 * @param r 結束下標 * @param i 第i個順序統計量 */public int randomizedSort(int arr[],int p,int r,int i){if(p==r)return arr[p];//對arr數組進行劃分,arr[q]即為數組arr的第q-p+1個順序統計量int q = partition(arr,p,r);int k = q-p+1;//如果i等於k,那麼arr[q]即為第i個順序統計量(第i小的元素)if(i==k)return arr[q];//如果i小於k,說明第i個順序統計量在arr[p..q-1]中else if(i<k)return randomizedSort(arr,p,q-1,i);//如果i大於k,說明第i個順序統計量在arr[q+1..r]中,只是在新數組中,第i個順序統計量就成了第i-k個順序統計量elsereturn randomizedSort(arr,q+1,r,i-k);}/** * 對數組arr[p..r]劃分成a[p..q]和a[q+1..r]兩個子數組,其中a[p..q]中的元素都小於a[q], * a[q+1..r]中的元素都大於a[q]。 * @param arr 需要劃分的數組 * @param p 數組起始下標 * @param r 數組結束下標 */public int partition(int arr[],int p,int r){//採用隨機演算法,期望在平均情況在,對數組的劃分能比較均稱int x = (int) (Math.random()*(r-p)+p);//arr[x]與arr[r]交換int temp = arr[x];arr[x] = arr[r];arr[r] = temp;//i為小元素部分中下標最大的位置,也就是它的下一個位置(即i+1)就是大元素部分下標最小的位置,初始化為p的前一個位置int i = p-1;//從p個元素開始,一直檢查到r前面的一個元素for(int j=p;j<r;j++){//如果arr[j]是比arr[r]小的元素,要放在小元素位置,由於i標記的是小元素部分下標最大的位置,//所以arr[j]應該被換到i+1的位置if(arr[j]<temp){i++;int w = arr[j];arr[j]= arr[i];arr[i]= w;}}//最後把arr[r]放在小元素部分和大元素部分中間arr[r] = arr[i+1];arr[i+1] = temp;return i+1;}//測試.....public static void main(String[] args) {int arr[] = {3,2,9,0,7,5,4,8,6,1};RandomizedSort rs = new RandomizedSort();int result = rs.randomizedSort(arr, 0, arr.length-1, 5);System.out.println(result);}}