最大N算法(前一版本的改进)

 

 

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]

*/

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值