傳統的求n個元素當中第k小的元素採用分置的思想,即取一確定數v(一般取44),順次比較n個數與該確定數(44)的大小,將小於該數的存入數組A1,等於該數的存入數組A2,大於該數的存入數組A3;接着比較k與三個數組的長度,若|A1|>=k,則重複上過程;若|A1|+|A2|>=k,則返回該確定數(即44);若|A1|+|A2|<k,則重複上過程,此時求A3數組當中第k-|A1|-|A2|小的元素。
該算法當中選取的確定數44較大,當參與比較的數較小時,分置思想並未得到體現,故採用隨機化的思想對該算法進行優化。
具體爲,隨機的從n個元素當中選擇一個數v作爲分置的邊界,其餘不變,具體代碼如下:
import java.util.ArrayList;
import java.util.Random;
public class RandomSelect {
public RandomSelect(){
}
public int RSelect(int [] a, int low, int hight, int k) {
Random random = new Random();
int v = random.nextInt(hight-1-low-1+1)+low;
int x = a[v];
ArrayList<Integer> a1 = new ArrayList<>();
ArrayList<Integer> a2 = new ArrayList<>();
ArrayList<Integer> a3 = new ArrayList<>();
for(int i=0;i<a.length;i++){
if(a[i]<x)
a1.add(a[i]);
if(a[i]==x)
a2.add(a[i]);
if(a[i]>x)
a3.add(a[i]);
}
if(a1.size() >= k){
int [] a11 = new int [a1.size()];
for(int i=0;i<a1.size();i++){
a11[i] = a1.get(i);
}
return RSelect(a11, 1, a11.length, k);
}
if(a1.size()+a2.size() >= k){
return x;
}
if(a1.size()+a2.size()+a3.size() >= k){
int [] a31 = new int [a3.size()];
for(int i=0;i<a3.size();i++){
a31[i] = a3.get(i);
}
return RSelect(a31, 1, a31.length, k-a1.size()-a2.size());
}
else
return 0;
}
}