A even more effective way dealing with this problem is to use linear time selection. The major idea of linear time selection is to recursively invoke the partition subroutine like a qucik sort which use a pivot to partition the array. After it finds the kth smallest element, all the elements less than or equals to it are relocated to the left of the pivot and those bigger than it are relocated to the right. So the solution to the original problem is to output all left elements to the kth smallest element and including itself.
The process of utilizing the partition subroutine to find the kth smallest element is like below :
1) Choose a pivot to partition the whole array, after partion all elements less than or equals to the pivot are relocated to the left of the pivot and those bigger than the pivot are relocated to the right.
2) Suppose the position of the pivot after partition is p, if p == k , then you find the kth smallest element otherwise,
a) if p < k , then kth smallest element is to the right of the pivot , then recursively to find the ( k-p ) th smallest element in the right subarray which is the kth smallest element in the whole array.
b) If p < k , then kth smallest element is to the left of the pivot , then recursively to find the kth smallest element in the left subarray which is the kth smallest element in the whole array.
Like quick sort, the performance depends on how you choose the pivot. For details , you can refer to : http://seanzhou.iteye.com/blog/1820426. The following codes implement the randomized pivot choosing whose expected time is O(n) and the medium of medium pivot choosing whose worst time is O(n).
The suffle method in the following codes is to do a random suffle of the orginal array, you can refer to :http://seanzhou.iteye.com/blog/1770403
public class KSmallestC { public static void main(String[] args) { assertEquals(new int[]{1,2,3,4}, getKSmallestByRandomPivot(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 4)); assertEquals(new int[]{1,2,3,4}, getKSmallestByRandomPivot(new int[]{10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, 4)); assertEquals(new int[]{21,22,14,18,9}, getKSmallestByRandomPivot(new int[]{27, 14, 18, 22, 21, 91, 33, 36, 42, 78 , 9, 65, 101, 29}, 5)); assertEquals(new int[]{1,2,3,4}, getKSmallestByMediumPivot(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 4)); assertEquals(new int[]{1,2,3,4}, getKSmallestByMediumPivot(new int[]{10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, 4)); assertEquals(new int[]{21,22,14,18,9}, getKSmallestByMediumPivot(new int[]{27, 14, 18, 22, 21, 91, 33, 36, 42, 78 , 9, 65, 101, 29}, 5)); } private static int[] getKSmallestByRandomPivot(int[] arr, int k ) { Selector s = new PartitionSelector(arr, new RandomPivotChooser()); s.select(k); int[] result = new int[k]; System.arraycopy(arr, 0, result, 0, k); return result; } private static int[] getKSmallestByMediumPivot(int[] arr, int k ) { Selector s = new PartitionSelector(arr, new MediumOfMediumChooser()); s.select(k); int[] result = new int[k]; System.arraycopy(arr, 0, result, 0, k); return result; } private static void assertEquals(int[] standard, int[] result) { Arrays.sort(standard); Arrays.sort(result); assert Arrays.equals(standard, result); } public interface Selector { int select( int index ); } public static class PartitionSelector implements Selector{ private int[] arr; private PivotChooser chooser; public PartitionSelector (int[] arr , PivotChooser chooser){ this.arr = arr; this.chooser = chooser; chooser.initialize(arr); } @Override public int select(int index) { if (index < 0 && index >= arr.length) throw new IllegalArgumentException("Index out of boundary"); int end = arr.length; int start = 0; int pivotIndex = chooser.choosePivot(start, end); pivotIndex = partition(start, end, pivotIndex); while (pivotIndex != index) { if( pivotIndex > index ) { end = pivotIndex; pivotIndex = chooser.choosePivot(start, end); pivotIndex = partition(start, end, pivotIndex); } else { start = pivotIndex + 1; pivotIndex = chooser.choosePivot(start, end); pivotIndex = partition(start, end, pivotIndex); } } return arr[index]; } private int partition(int start, int end , int pivotIndex){ //swap with the partition element with the first one int temp = arr[start]; arr[start] = arr[pivotIndex]; arr[pivotIndex] = temp; int pivot = arr[start]; int i=start+1,j=end-1; while( i <= j ) { while ( i <= j && arr[i] <= pivot ) i ++; if (i > j) break; while (arr[j] > pivot ) j--; if ( i > j) break; temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } i--; arr[start] = arr[i]; arr[i] = pivot; return i; } } public static class RandomPivotChooser implements PivotChooser{ private int[] arr; private boolean init; private void shuffle() { Random random = new Random(); int temp, j; for ( int i = 1 ; i < arr.length ; i ++ ) { j = random.nextInt(i+1); temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } @Override public int choosePivot(int start, int end) { if (! init ) throw new IllegalStateException("Pivot Chooser not initialized!"); if ( start >= end ) throw new IllegalArgumentException("end should bigger than start!"); if ( end > arr.length ) throw new IllegalArgumentException("end should not bigger than arry length!"); return start; } @Override public void initialize(int[] arr) { this.arr = arr; shuffle(); this.init = true; } } public static class MediumOfMediumChooser implements PivotChooser{ private int[] arr; private boolean init; @Override public int choosePivot(int start, int end) { if ( start >= end ) throw new IllegalArgumentException("end should bigger than start!"); if ( end > arr.length ) throw new IllegalArgumentException("end should not bigger than arry length!"); if (! init ) throw new IllegalStateException("Pivot Chooser not initialized!"); if ( end - start <= 2) { return start; } // sort elements in each block int BLOCK_SIZE = 5; int i = BLOCK_SIZE; int num = 1; for ( ; i < end ; i += BLOCK_SIZE , num ++) { insertionSort(i - BLOCK_SIZE, i); } i -= BLOCK_SIZE; insertionSort(i, end); // choose medium of each group int medium = BLOCK_SIZE/2; int[] mediums = new int[num]; int r = ( i + end ) / 2; // medium item in last block i = 0 ; for ( int j = medium; i < num - 1 ; j += BLOCK_SIZE, i ++ ) { mediums[i] = arr[j]; } mediums[i] = arr[r]; Selector selector = new PartitionSelector(mediums, new MediumOfMediumChooser()); int pivot = selector.select(num/2); for ( i = start; i < end; i ++) { if ( arr[i] == pivot) return i; } throw new IllegalStateException("Medium of Medium didn't find a correct pivot!"); } @Override public void initialize(int[] arr) { this.arr = arr; this.init = true; } private void insertionSort(int start, int end) { int temp; for ( int i = start + 1; i < end ; i ++ ) { for ( int j = i ; j > 0 ; j --) { if ( arr[j] < arr[j-1] ) { temp = arr[j]; arr[j] = arr[j-1]; arr[j-1] = temp; } else { break; } } } } } public interface PivotChooser{ //return the index of the new pivot int choosePivot(int start, int end); void initialize(int[] arr); } }
相关推荐
Finding Top-k Shortest Simple Paths with Diversity.pptx
Learning the Kernel and Finding Performance Problems with KFI
Finding scientific topics
Finding Tiny Faces
finding a majority among n votes.pdffinding a majority among n votes.pdffinding a majority among n votes.pdffinding a majority among n votes.pdfv
VisionPro_Shape Finding 帮助文档,英文版说明直线、圆、椭圆的查找
论文翻译:On Finding Socially Tenuous Groups for Online Social Networks。现有的寻找社会群体的研究主要集中在社交网络中的密集子图。然而,寻找社会脆弱的群体也有许多重要的应用。在本文中,我们引入了K三角的...
FINDING STRUCTURE WITH RANDOMNESS.pdf描述了一系列的矩阵的方法。
finding alphas a quantitative approach to building trading strategies MOBI电子书
Samet Hanan经典文章Trans on PAMI,K近邻模式识别分类器新方法。
NRF528XX Direction Finding -AOA AOD
Finding the prime numbers in range.
这个是关于找出一个有向、无向图中的前k个最小花费的斯坦纳树,采用了带系数的多项式算法。
Finding Metric Structure in Information Theoretic Clustering
Finding People in Images and Videos,dalal大神的毕业论文130多页,我打印出一部分看过,理解hog很有用,光流部分还没看。还有另一个人毕业论文,放这里,怕自己以后找不到
Finding Preimages in Full MD5 Faster Than Exhaustive Search
Finding Collisions in the Full SHA-1
Finding overlapping communities in networks by label propagation论文
( Wiley Taming the Big Data Tidal Wave, Finding Opportunities in Huge Data Streams with Advanced Analytics (2012).pdf )
Finding lungs in CT 是基于肺部 CT 影像分割处理的数据集,其包含一系列 CT 影像中对肺部影像的分割,并以此识别和估计肺部容积量。 该数据集包含 4 名患者的数据,以 nifti 格式的图像和分段肺面罩为主,由 ...