64 数据流中的中位数

题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
(1)最简单的方法,使用工具类对其进行排序,然后取其中位数即可。

import java.util.*;
public class Solution {

    ArrayList<Integer> arr = new ArrayList();
    public void Insert(Integer num) {
        arr.add(num);
    }

    public Double GetMedian() {
        Collections.sort(arr);
        int len = arr.size();
        if(len % 2 == 0){
            return ((double)arr.get(len/2) + (double)arr.get(len/2-1)) / 2;           
        }else
            return (double)arr.get(len/2);

    }
}

(2)然后,使用快排划分的算法;

import java.util.*;
public class Solution {

    ArrayList<Integer> arr = new ArrayList();
    public void Insert(Integer num) {
        arr.add(num);
    }

    public Double GetMedian() {
        int low = 0;
        int high = arr.size() - 1;
        int index = partition(arr,low,high);
        int mid = arr.size() / 2;
        while(mid != index){
            if(index > mid)
                index = partition(arr,low,index - 1);
            else
                index = partition(arr,index+1,high);
        }
        int res1 = arr.get(index);
        if(arr.size() % 2 == 0){
            mid = arr.size() / 2  - 1;
            while(mid != index){
                if(index > mid)
                    index = partition(arr,low,index - 1);
                else
                    index = partition(arr,index+1,high);
            }
            int res2 = arr.get(index);
            return ((double)res1 + res2) / 2;
        }else
            return (double)res1;

    }
     public int partition( ArrayList<Integer> input,int low,int high){
       int val = input.get(low);
        while(low < high){
            while(low<high && input.get(high)>=val)
                high--;
            input.set(low,input.get(high));
            while(low<high && input.get(low)<val)
                low++;
            input.set(high,input.get(low));           
        }
        input.set(low,val);
        return low;
    }
}

3、
(1)使用大小堆原理:中位数把数组分为了两部分,根据最大堆获得左边部分最大的数,最小堆获得右边部分最小的数。=》可得中位数
(2)用最大堆实现左边的容器,最小堆实现右边的容器。插入时间效率O(logn),得到堆顶的时间效率是O(1)。
(3)得保证两个堆的数据数目的差不能超过1。为了实现平均分配,可以将数据总数是偶数时,把新的数插入到右边的最小堆;总数为奇数时,把新数插入到左边的最大堆。
(4)还得保证最大堆的所有数据都要小于最小堆的数据。==》当总数为奇数时,要插入最大堆,那么先把它插入最小堆,然后取最小堆的堆顶–最小值,然后再插入到最大堆(最终插入到最大堆的是原最小堆的最小元素)。偶数时,同理!

import java.util.*;
public class Solution {

    int count = 0;
    PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
    PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11,new Comparator<Integer>(){
        public int compare(Integer o1,Integer o2){
            return o2 - o1;
        }
    });
    public void Insert(Integer num) {
        if(count % 2 == 0){
            maxHeap.offer(num);
            int filterMaxNum = maxHeap.poll();
            minHeap.offer(filterMaxNum);
        }else{
            minHeap.offer(num);
            int filterMinNum = minHeap.poll();
            maxHeap.offer(filterMinNum);
        }
        count++;
    }

    public Double GetMedian() {
        if(count % 2 == 0)
            return (Double.valueOf(minHeap.peek()) + maxHeap.peek())/2;
        else
            return Double.valueOf(minHeap.peek());
    }

}

参考:https://www.nowcoder.com/profile/645151/codeBookDetail?submissionId=1521636
内容如下:
讲解很详细

public void Insert(Integer num) {
    if (count %2 == 0) {//当数据总数为偶数时,新加入的元素,应当进入小根堆
        //(注意不是直接进入小根堆,而是经大根堆筛选后取大根堆中最大元素进入小根堆)
        //1.新加入的元素先入到大根堆,由大根堆筛选出堆中最大的元素
        maxHeap.offer(num);
        int filteredMaxNum = maxHeap.poll();
        //2.筛选后的【大根堆中的最大元素】进入小根堆
        minHeap.offer(filteredMaxNum);
    } else {//当数据总数为奇数时,新加入的元素,应当进入大根堆
        //(注意不是直接进入大根堆,而是经小根堆筛选后取小根堆中最大元素进入大根堆)
        //1.新加入的元素先入到小根堆,由小根堆筛选出堆中最小的元素
        minHeap.offer(num);
        int filteredMinNum = minHeap.poll();
        //2.筛选后的【小根堆中的最小元素】进入大根堆
        maxHeap.offer(filteredMinNum);
    }
    count++;
}

该题具有动态性,取决于使用的数据结构:
(1)无序数组—–插入O(1),查找O(n);
(2)有序数组/链表—插入O(n),查找O(1) 链表定义两个指针??
(3)二叉排序树—插入【平均O(logn),最差O(n)】
查找【平均O(logn),最差O(n)】
(4)AVL O(logn),O(1)
(5)最大最小堆:O(logn),O(1)

猜你喜欢

转载自blog.csdn.net/xuchonghao/article/details/80527244