zoukankan      html  css  js  c++  java
  • 流求中位数

    package day5;
    
    import java.util.Arrays;
    import java.util.Comparator;
    import java.util.PriorityQueue;
    
    /*
     * 问题:
     * 如何得到一个数据流中的中位数?
     * 如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。
     * 如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
     * 
     * 思路:
     * 采用堆,一个大根堆,一个小根堆。(小根堆存放偏大得数,大根堆存放偏小的数)
     * 第一个数先读到大根堆中,
     * 后面的数,对比大根堆堆顶,如果小于等于堆顶放入大根堆,
     * 否则尝试放入小根堆,如果小根堆空,放入,否者对比小根堆堆顶,大于堆顶放入小根堆。否则放入大根堆。
     * 
     * 如果两个堆相差>1;取出堆顶,放到数目少的里面。
     * 
     */
    public class Code04_MedianInDatastream {
        
        
        public static class MedianHolder{
            PriorityQueue<Integer> minHeap;
            PriorityQueue<Integer> maxHeap; 
            public MedianHolder(){
                this.minHeap = new PriorityQueue<>();
                this.maxHeap = new PriorityQueue<>(new MaxHeapComparator());
            }
            public void modify() {
                int count = maxHeap.size() - minHeap.size();
                if (Math.abs(count) >1) {
                    if(count >0) {
                        minHeap.add(maxHeap.poll());
                    }else {
                        maxHeap.add(minHeap.poll());
                    }
                }
            }
            //naive!!!!!要考虑全面!!为空呢?
            
            public void add (int num) {
                if(maxHeap.isEmpty()) {
                    maxHeap.add(num);
                    return ;
                }
                if(num <= maxHeap.peek()) {//注意这里是小于大根堆堆顶
                    maxHeap.add(num);
                }else {//否者尝试放入小根堆,尝试!!!尝试!!!
                    if(minHeap.isEmpty()) {
                        minHeap.add(num);
                        return ;
                    }
                    if(num >= minHeap.peek()) {
                        minHeap.add(num);
                    }else {
                        maxHeap.add(num);
                    }
                }
                modify();
            }
            public Integer getMedian() {
                int maxHeapSize = maxHeap.size();
                int minHeapSize = minHeap.size();
                if (maxHeap.isEmpty() && minHeap.isEmpty()) {
                    return null;
                }
                Integer maxHeapHead =  maxHeap.peek();
                Integer minHeadHead = minHeap.peek();
                if(((maxHeapSize + minHeapSize) & 1) == 0){
                    return (maxHeapHead + minHeadHead)/2;
                }
                return minHeapSize > maxHeapSize ? minHeadHead :maxHeapHead;
            }
        }
        
        
        public static class MaxHeapComparator implements Comparator<Integer>{
    
            @Override
            public int compare(Integer o1, Integer o2) {
                // TODO Auto-generated method stub
                return o2 -o1;
            }
    
        
            
        }
        
    
        // for test
            public static int[] getRandomArray(int maxLen, int maxValue) {
                int[] res = new int[(int) (Math.random() * maxLen) + 1];
                for (int i = 0; i != res.length; i++) {
                    res[i] = (int) (Math.random() * maxValue);
                }
                return res;
            }
    
            // for test, this method is ineffective but absolutely right
            public static int getMedianOfArray(int[] arr) {
                int[] newArr = Arrays.copyOf(arr, arr.length);
                Arrays.sort(newArr);
                int mid = (newArr.length - 1) / 2;
                if ((newArr.length & 1) == 0) {
                    return (newArr[mid] + newArr[mid + 1]) / 2;
                } else {
                    return newArr[mid];
                }
            }
    
            public static void printArray(int[] arr) {
                for (int i = 0; i != arr.length; i++) {
                    System.out.print(arr[i] + " ");
                }
                System.out.println();
            }
    
            public static void main(String[] args) {
                boolean err = false;
                int testTimes = 200000;
                for (int i = 0; i != testTimes; i++) {
                    int len = 30;
                    int maxValue = 1000;
                    int[] arr = getRandomArray(len, maxValue);
                    MedianHolder medianHold = new MedianHolder();
                    for (int j = 0; j != arr.length; j++) {
                        medianHold.add(arr[j]);
                    }
                    if (medianHold.getMedian() != getMedianOfArray(arr)) {
                        err = true;
                        printArray(arr);
                        System.out.println(medianHold.getMedian());
                        break;
                    }
                }
                System.out.println(err ? "Oops..what a fuck!" : "today is a beautiful day^_^");
    
            }
    
    
    }
  • 相关阅读:
    对线性回归算法的评测
    HIVE cdh5.15.1搭建
    解决Shuffle$ShuffleError: error in shuffle in fetcher错误
    启动YARN资源管理器
    linux检测活体ip并邮件提醒
    Hadoop的NameNode进入安全模式
    Java操作Hadoop-HDFS API Maven环境搭建
    Hadoop CDH版本安装和启动(CentOS7)
    基于Redis的Nginx服务器集群session共享
    基于Memcached的Nginx服务器集群session共享
  • 原文地址:https://www.cnblogs.com/codinghard/p/11489113.html
Copyright © 2011-2022 走看看