MaxNAlgorithm比最简单的排序后取最大的n位, 效率高十陪以上(当然需排序数组也要有足够大且n与数组大小差距足够大才行; 测试结果只是个比较而已,因为vm没有先预热以及相应参数配置)。
最简单的排序后取最大的n位: array size 乘于 array size 的比较。
MaxNAlgorithm:n 乘于 array size 的比较。
这个算是对前一版本的改进:
因为之前直接利用PriorityQueue实现了一个(效率只提高三陪以上)
http://blog.csdn.net/yang_net/archive/2010/10/24/5962010.aspx
1。 算法实现
/**
*
*/
package algorithm.max;
import java.util.Arrays;
/**
* Max N Primitive Algorithm
*
* @author yangwm Nov 1, 2010 9:25:02 PM
*/
public class MaxNAlgorithmPrimitive {
/**
* max + n
*
* @param <int>
* @param input
* @param n
* @return
*/
public static int[] max(int[] input, int n) {
if (n > input.length) {
n = input.length;
}
int[] result = new int[n];
int[] temp = Arrays.copyOf(input, n);
Arrays.sort(temp);
for (int i = temp.length - 1, resultIdx = 0; i >= temp.length - n; i--) {
result[resultIdx++] = temp[i];
}
//System.out.println(Arrays.toString(result));
for (int i = n; i < input.length; i++) {
add(input[i], result);
}
return result;
}
/**
* add
*
* 使用orderPosition效率高于binaryPosition
*
* @param <E>
* @param x
* @param result
* @param comparator
*/
private static <E> void add(E x, E[] result, Comparator<? super E> comparator) {
int k = orderPosition(x, result, comparator); // binaryPosition(x, result, comparator);
/*
* 根据返回的数组下标交换位置 (让x元素排在比它的小的元素前面)
*/
if (k < result.length - 1) {
int srcIdx = k + 1;
if (srcIdx != result.length - 1) { // 已经是最后一位不需要移动整个数组
int destIdx = srcIdx + 1; // 后移一位
System.arraycopy(result, srcIdx, result, destIdx, result.length - destIdx);
}
result[srcIdx] = x;
}
}
/**
* 由小到大定位:找出大于等于x元素的数组下标,没有大于等于x元素则返回-1
*
* @param <int>
* @return
*/
private static int orderPosition(int x, int[] result) {
//System.out.println("binaryPosition:" + x + ", " + Arrays.toString(result));
int k = result.length - 1;
while (k >= 0) {
int e = result[k];
//System.out.println("result[" + k + "]=" + e);
if (x >= e) {
k--;
} else {
break;
}
}
//System.out.println("k:" + k);
return k;
}
/**
* 二分定位:找出大于等于x元素的数组下标,没有大于等于x元素则返回-1
* Arrays.binarySearch的变体
*
* @param <E>
* @param x
* @param result
* @param comparator
* @return
*/
private static int binaryPosition(int x, int[] result) {
//System.out.println("binaryPosition:" + x + ", " + Arrays.toString(result));
int k = -1;
int left = 0;
int right = result.length - 1;
while (left <= right) {
int mid = (left + right) >>> 1;
int midVal = result[mid];
if (x < midVal) {
left = mid + 1;
} else if (x > midVal) {
right = mid - 1;
} else {
break;
}
}
k = left - 1;
//System.out.println("k:" + k);
return k; // key not found.
}
/**
* @param args
*/
public static void main(String[] args) {
int[] input = new int[] { 2, 7, 6, 8, 9, 18, 11, 5, 3, 20 };
int n = 3;
System.out.println("------MaxNPrimitiveAlgorithm Array max n-------");
int[] result = max(input, n);
System.out.println(Arrays.toString(result));
}
}
package algorithm.max;
import java.util.Arrays;
/**
* top n algorithm
*
* 算法来自一道面试题注记 - 庄周梦蝶 - BlogJava
* http://www.blogjava.net/killme2008/archive/2010/10/28/336357.html
*
* @author yangwm Oct 31, 2010 6:39:46 PM
*/
public class TopNAlgorithm {
/**
* 求数组的前n个元素
*
* @param anyOldOrderValues
* @param n
* @return
*/
public static int[] findTopNValues(int[] anyOldOrderValues, int n) {
int[] result = new int[n];
findTopNValues(anyOldOrderValues, 0, anyOldOrderValues.length - 1, n,
n, result);
return result;
}
public static final void findTopNValues(int[] a, int p, int r, int i,
int n, int[] result) {
// 全部取到,直接返回
if (i == 0)
return;
// 只剩一个元素,拷贝到目标数组
if (p == r) {
System.arraycopy(a, p, result, n - i, i);
return;
}
if (i > r - p + 1 || i < 0)
throw new IllegalArgumentException();
// 划分
int q = medPartition(a, p, r);
// 计算右子段长度
int k = r - q + 1;
// 右子段长度恰好等于i
if (i == k) {
// 拷贝右子段到结果数组,返回
System.arraycopy(a, q, result, n - i, i);
return;
} else if (k > i) {
// 右子段比i长,递归到右子段求前i个元素
findTopNValues(a, q + 1, r, i, n, result);
} else {
// 右子段比i短,拷贝右子段到结果数组,递归左子段求前i-k个元素
System.arraycopy(a, q, result, n - i, k);
findTopNValues(a, p, q - 1, i - k, n, result);
}
}
public static int medPartition(int x[], int p, int r) {
int len = r - p + 1;
int m = p + (len >> 1);
if (len > 7) {
int l = p;
int n = r;
if (len > 40) { // Big arrays, pseudomedian of 9
int s = len / 8;
l = med3(x, l, l + s, l + 2 * s);
m = med3(x, m - s, m, m + s);
n = med3(x, n - 2 * s, n - s, n);
}
m = med3(x, l, m, n); // Mid-size, med of 3
}
if (m != r) {
int temp = x[m];
x[m] = x[r];
x[r] = temp;
}
return partition(x, p, r);
}
private static int med3(int x[], int a, int b, int c) {
return x[a] < x[b] ? (x[b] < x[c] ? b : x[a] < x[c] ? c : a)
: x[b] > x[c] ? b : x[a] > x[c] ? c : a;
}
public static int partition(int a[], int p, int r) {
int x = a[r];
int i = p - 1;
for (int j = p; j < r; j++) {
if (a[j] < x) {
i++;
int temp = a[j];
a[j] = a[i];
a[i] = temp;
}
}
int temp = a[i + 1];
a[i + 1] = a[r];
a[r] = temp;
// System.out.println((i+1-p)+" "+(r-i-1));
return i + 1;
}
/**
* @param args
*/
public static void main(String[] args) {
int[] input = new int[] { 2, 7, 6, 8, 9, 18, 11, 5, 3, 20 };
int n = 3;
System.out.println("------TopNAlgorithm Array findTopNValues n-------");
int[] result = findTopNValues(input, n);
System.out.println(Arrays.toString(result));
}
}
/*
------TopNAlgorithm Array findTopNValues n-------
[18, 20, 11]
*/
/**
*
*/
package algorithm.max;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Max N Algorithm Primitive Bench
*
* @author yangwm Nov 1, 2010 9:25:14 PM
*/
public class MaxNAlgorithmPrimitiveBench {
/**
* @param args
*/
public static void main(String[] args) {
/*
*
*/
int inputTotal = 10000000;
int n = 10;
/*
* test data
*/
List<Integer> inputList = new ArrayList<Integer>(inputTotal);
for (int i = 0; i < inputTotal; i++) {
inputList.add(i);
}
Collections.shuffle(inputList);
System.out.println("test begin inputTotal: " + inputTotal + ", n: " + n);
System.out.println("test data inputList.size(): " + inputList.size());
//-----------------------------------------------------------------
int[] inputArray = new int[inputList.size()];
for (int i = 0; i < inputArray.length; i++) {
inputArray[i] = inputList.get(i);
}
System.out.println("-------JDK Arrays.sort max n-------");
/*
* max and test print
*/
long begin = System.currentTimeMillis();
Arrays.sort(inputArray);
int[] resultArray = new int[n];
for (int i = inputArray.length - 1, resultIdx = 0; i >= inputArray.length - n; i--) {
resultArray[resultIdx++] = inputArray[i];
}
long end = System.currentTimeMillis();
System.out.println("cosume: " + (end - begin) + " ms");
System.out.println("resultArray.length: " + resultArray.length);
System.out.println("resultArray of first ten : " + Arrays.toString(resultArray));
//-----------------------------------------------------------------
inputArray = new int[inputList.size()];
for (int i = 0; i < inputArray.length; i++) {
inputArray[i] = inputList.get(i);
}
System.out.println("-------MaxNAlgorithmPrimitiveBench Array top n-------");
/*
* max and test print
*/
begin = System.currentTimeMillis();
resultArray = MaxNAlgorithmPrimitive.max(inputArray, n);
end = System.currentTimeMillis();
System.out.println("cosume: " + (end - begin) + " ms");
System.out.println("resultArray.length: " + resultArray.length);
System.out.println("resultArray of first ten : " + Arrays.toString(resultArray));
//-----------------------------------------------------------------
inputArray = new int[inputList.size()];
for (int i = 0; i < inputArray.length; i++) {
inputArray[i] = inputList.get(i);
}
System.out.println("-------TopNAlgorithmBench Array top n-------");
/*
* max and test print
*/
begin = System.currentTimeMillis();
resultArray = TopNAlgorithm.findTopNValues(inputArray, n);
end = System.currentTimeMillis();
System.out.println("cosume: " + (end - begin) + " ms");
System.out.println("resultArray.length: " + resultArray.length);
System.out.println("resultArray of first ten : " + Arrays.toString(resultArray));
}
}
/*
test begin inputTotal: 10000000, n: 10
test data inputList.size(): 10000000
-------JDK Arrays.sort max n-------
cosume: 1781 ms
resultArray.length: 10
resultArray of first ten : [9999999, 9999998, 9999997, 9999996, 9999995, 9999994, 9999993, 9999992, 9999991, 9999990]
-------MaxNAlgorithmPrimitiveBench Array top n-------
cosume: 78 ms
resultArray.length: 10
resultArray of first ten : [9999999, 9999998, 9999997, 9999996, 9999995, 9999994, 9999993, 9999992, 9999991, 9999990]
-------TopNAlgorithmBench Array top n-------
cosume: 141 ms
resultArray.length: 10
resultArray of first ten : [9999996, 9999998, 9999999, 9999997, 9999991, 9999993, 9999992, 9999994, 9999995, 9999990]
*/