http://javatroops.blogspot.com/2012/10/median-of-medians-to-find-kth-smallest.html
Given an array of unsorted integers find the Kth smallest element using "Median of Medians".
This method is guaranteed to work in max linear time
if you just get the student who is ranked50th in the class. Now in another single pass (O(n) ), you can just compare the marks of the rest of the students with the selected student.
http://javatroops.blogspot.com/2012/10/median-of-medians-to-find-kth-smallest.html
Code from http://yiqi2.wordpress.com/2013/07/03/median-of-medians-selection-algorithm/
Quick Select:
http://ajeetsingh.org/2013/09/20/median-of-medians-find-kth-largest-element-from-a-large-un-sorted-array/
https://github.com/email4rohit/interview-java-algo/blob/master/MedianOfMedians.java
Read full article from Median of Medians
Given an array of unsorted integers find the Kth smallest element using "Median of Medians".
This method is guaranteed to work in max linear time
if you just get the student who is ranked
http://javatroops.blogspot.com/2012/10/median-of-medians-to-find-kth-smallest.html
private static int select(Integer[] a, int k) { | |
if (a.length <= 10) | |
{ | |
Arrays.sort(a); | |
return a[k-1]; | |
} | |
int n = a.length; | |
//partition L into subsets S[i] of five elements each | |
// (there will be n/5 subsets total). | |
List<Integer[]> list = new ArrayList<Integer[]>(); | |
// don't need temp list. | |
int cnt = 0; | |
int m = n/5; | |
for( int i = 0; i < m; i++ ) { | |
Integer[] arr = new Integer[5]; | |
for( int j = 0; j < 5; j++ ) { | |
if( cnt == n ) | |
break; | |
arr[j] = a[cnt++]; | |
} | |
Arrays.sort(arr); | |
list.add(arr); | |
} | |
Integer[] x = new Integer[m]; | |
for (int i = 0; i< m; i++ ) { | |
x[i] = list.get(i)[2]; | |
} | |
int v = x[0]; | |
if(x.length > 2) { | |
v = (x.length%2 == 0)? x[x.length%2-1]: x[x.length/2]; | |
} | |
// partition L into L1<M, L2=M, L3>M ==> we can combine these two steps | |
Integer[] l = partition_l( a, v ); | |
Integer[] r = partition_r( a, v ); | |
if( k == l.length+1 ) { | |
return v; | |
} else if( k <= l.length ){ | |
return select(l,k); | |
} else { | |
return select(r,k-l.length-1); | |
} | |
} | |
private static Integer[] partition_l( Integer[] a, int pivot ) { | |
if( a.length == 0) | |
return a; | |
int j = 0; | |
Integer[] b = new Integer[a.length]; | |
for( int i = 0; i < a.length; i++ ) { | |
if(a[i] < pivot) { | |
b[j++] = a[i]; | |
} | |
} | |
Integer[] l = new Integer[j]; | |
System.arraycopy(b, 0, l, 0, j); | |
return l; | |
} | |
private static Integer[] partition_r( Integer[] a, int pivot ) { | |
if( a.length == 0) | |
return a; | |
int j = 0; | |
Integer[] b = new Integer[a.length]; | |
for( int i = 0; i < a.length; i++ ) { | |
if(a[i] > pivot) { | |
b[j++] = a[i]; | |
} | |
} | |
Integer[] r = new Integer[j]; | |
System.arraycopy(b, 0, r, 0, j); | |
return r; | |
} |
Code from http://yiqi2.wordpress.com/2013/07/03/median-of-medians-selection-algorithm/
private
int
find(
int
[] a,
int
s,
int
n,
int
k ) {
// start point s, length n, find k-th number
if
( n ==
1
&& k ==
1
)
return
a[s];
int
m = (n+
4
) /
5
;
int
[] mid =
new
int
[m];
for
(
int
i=
0
; i<m; i++) {
int
t = s+i*
5
;
// 5-elements block pointer
if
( n-t >
4
) {
sort(a, t,
5
);
// sort 5 elements
mid[i] = a[t+
2
];
}
else
{
// less than 5 left
sort(a, t, n-t);
// sort the rest
mid[i] = a[t+(n-t-
1
)/
2
];
}
}
int
pivot = find(mid,
0
, m, (m+
1
)/
2
);
for
(
int
i=
0
; i<n; i++) {
// find pivot location
if
(a[s+i] == pivot ) {
swap(a, s+i, s+n-
1
);
break
;
}
}
int
pos =
0
;
for
(
int
i=
0
; i<n-
1
; i++) {
// using pivot to part
if
( a[s+i] < pivot ) {
if
( i != pos )
swap(a, s+i, s+pos);
pos++;
}
}
swap(a, s+pos, s+n-
1
);
if
( pos == k-
1
)
return
pivot;
else
if
( pos > k-
1
)
return
find(a, s, pos, k);
else
return
find(a, s+pos+
1
, n-pos-
1
, k-pos-
1
);
}
Quick Select:
http://ajeetsingh.org/2013/09/20/median-of-medians-find-kth-largest-element-from-a-large-un-sorted-array/
int
findKthElement(
int
[] input,
int
K){
int
lo =
0
, hi = input.length -
1
;
while
(hi > lo) {
int
i = partition(input, lo, hi);
if
(i > k)
hi = i -
1
;
else
if
(i < k)
lo = i +
1
;
else
return
input[i];
}
return
input[lo];
}
int
partition(
int
[] input,
int
lo,
int
hi) {
int
i = lo;
int
j = hi +
1
;
int
pivot = input[lo];
while
(
true
) {
while
(less(input[++i], pivot))
if
(i == hi)
break
;
while
(less(pivot, input[--j]))
if
(j == lo)
break
;
if
(i >= j)
break
;
exchange(input[i], input[j]);
}
exchange(input[lo], input[j]);
return
j;
}
Read full article from Median of Medians