精华内容
下载资源
问答
  • 以下摘自百度百科:对于有限的数集,可以通过把所有观察值高低排序后找出正中间的一个作为中位数。如果观察值有偶数个,通常取最中间的两个数值的平均数作为中位数。 由概念可得,对于一个有小到大排序好的数据集,...

    1、概念

    以下摘自百度百科:对于有限的数集,可以通过把所有观察值高低排序后找出正中间的一个作为中位数。如果观察值有偶数个,通常取最中间的两个数值的平均数作为中位数。

    由概念可得,对于一个有小到大排序好的数据集,若其长度是n,n为奇数,则中位数就是n/2下标的位置。如果数据集的长度是n,n为偶数,则中位数就是n/2与n/2+1下标的位置的平均值。

    获取中位数的主要时间复杂度,由排序算法的时间复杂度决定,最快为nLog(n)。

    2、优化解法

    首先将数据集的个数分成奇数和偶数两种情况进行探讨,同时发现这两种情况有共同点,如下图所示。数据集数据长度为2n+1或2n时,我们只需要把最大n+1构建成一个新的Collection,再根据奇偶情况计算中位数即可。

    而JDK恰巧有这样的数据结构:PriorityQueue(优先队列),其通过完全二叉树实现的小顶堆,插入数据的时间复杂度为Log(n),并且堆顶是最小元素。

    Java实现如下:

    public class Math {
        /**
         * 获取中位数
         * @param arr
         * @return
         */
        public Double getMedianNum(int[] arr){
            //边界值
            if(arr == null || arr.length == 0){
                return null;
            }
    
            //考虑到arr长度为1时交由下面业务逻辑处理耗时也耗空间,此处做提前判断时间复杂度也才多O(1)
            if(arr.length == 1){
                return (double) arr[0];
            }
            
            // 默认是小顶堆,大顶堆为new PriorityQueue<>(Collections.reverseOrder())
            PriorityQueue<Integer> minPQ = new PriorityQueue<>();
            int length = arr.length;
            int k = length/2+1;
    
            for(int i = 0;i<k;i++){
                minPQ.add(arr[i]);
            }
            for(int i = k;i<length;i++){
                if(minPQ.peek() < arr[i]){
                    minPQ.poll();
                    minPQ.add(arr[i]);
                }
            }
            if (length % 2 == 0){
                return (minPQ.poll() + minPQ.peek())/ 2.0;
            } else{
                return minPQ.peek().doubleValue();
            }
        }
    }

    展开全文
  • 基本思路:对数组进行排序,直接访问数组中位数 double MIDnum(vector<int>& array) { if(array.empty()) return -1; int midIndex = (array.size() - 1) / 2; sort(array.begin(), array.end()); if...

    一.利用排序进行查找中位数

    基本思路:对数组进行排序,直接访问数组中位数

    double MIDnum(vector<int>& array) {
        if(array.empty())
            return -1;
    	int midIndex = (array.size() - 1) / 2;
    	sort(array.begin(), array.end());
    	if (array.size() % 2 == 1) {
    		return (double)array[midIndex];
    	}
    	return ((double)array[midIndex] + (double)array[midIndex + 1]) / 2;
    }

    二.类似于快速排序,采用的是分而治之的思想.

    基本思路:任意挑选一个元素,以该元素为基准点,将数组分为两部分.左部分都是小于基准点的,右部分都是大于基准点的.如果运气好的话,基准值正好就是中位数.

    int partion(vector<int>& array, int begin, int end) {
    	int start = begin;
    	int key = array[begin];
    	while (begin < end) {
    		while (begin < end && array[end] >= key) {
    			end--;
    		}
    		while (begin < end && array[begin] <= key) {
    			begin++;
    		}
    		swap(array[begin], array[end]);
    	}
    	swap(array[start], array[begin]);
    	return begin;
    }	
    
    double getNum(vector<int>& array, int midIndex) {
    	int left = 0;
    	int right = array.size() - 1;
    	int index = -1;
    	while (index != midIndex) {
    		index = partion(array, left, right);
    		if (index > midIndex) {
    			right = index - 1;
    		}
    		else if (index < midIndex) {
    			left = index + 1;
    		}
    		else
    			break;
    	}
    	return (double)array[index];
    }
    double midNum(vector<int>& array) {
    	if (array.empty()) {
    		return -1;
    	}
    	int midIndex = (array.size() - 1) / 2;
    	if (array.size() % 2 == 1) {
    		return getNum(array, midIndex);
    	}
    	return (getNum(array, midIndex) + getNum(array, midIndex + 1)) / 2;
    }

    三.利用最小堆查找中位数

    基本思路:首先将数组的前(n+1)/2个元素建立最小堆.后序元素进行判断入堆或舍弃.下一个元素与堆顶元素进行对比,如果大于堆顶元素则删除堆顶元素,该元素入堆,否则什么都不做.

    double MidNum(vector<int>& array) {
        if(array.empty())
            return -1;
    	int sz = array.size() / 2 + 1;
    	cout << sz << endl;
    	priority_queue<int,vector<int>,greater<int>> pq;
    	for (int i = 0; i < sz; i++) {
    		pq.push(array[i]);
    	}
    	for (int i = sz; i < array.size(); i++) {
    		if (array[i] > pq.top()) {
    			pq.pop();
    			pq.push(array[i]);
    		}
    	}
    	if (array.size() % 2 == 1) {
    		return (double)pq.top();
    	}
    	double val1 = double(pq.top());
    	pq.pop();
    	double val2 = double(pq.top());
    	return (val1 + val2) / 2;
    }

    展开全文
  • 中位数,就是数组排序后处于数组最中间的那个元素。如果数组长度是奇数,最中间就是位置为(n+1)/2的那个元素。如果是偶数,中位数是位置为n/2和位置为n/2+1的两个元素的和除以2的结果。 算法要求:输入一个整数数...

    中位数,就是数组排序后处于数组最中间的那个元素。如果数组长度是奇数,最中间就是位置为(n+1)/2的那个元素。如果是偶数,中位数是位置为n/2和位置为n/2+1的两个元素的和除以2的结果。

    算法要求:输入一个整数数组,求出本数组的中位数。

    思路1:将数组排序,然后直接从排序数组中找出中位数。时间复杂度取决于排序算法,最快是快速排序,O(nlogn),或者是非比较的基数排序,时间为O(n),空间为O(n)。

    思路2:采用快速排序的分治partition过程。任意挑一个元素,以该元素为支点,将数组分成两部分,左边是小于等于支点的,右边是大于支点的。如果左侧长度正好是(n-1)/2,那么支点恰为中位数。如果左侧长度<(n-1)/2, 那么中位数在右侧,反之,中位数在左侧。 进入相应的一侧继续寻找中位数。

    思路3:将数组的前(n+1)/2个元素建立一个最小堆。然后,对于下一个元素,和堆顶的元素比较,如果小于等于,丢弃之,如果大于,则用该元素取代堆顶,再调整堆,接着看下一个元素。重复这个步骤,直到数组为空。当数组都遍历完了,堆顶的元素即是中位数。

    在Java中,PriorityQueue是一个基于优先级堆的无界优先级队列,默认是一个最小堆。
    在这里插入图片描述
    实现如下:

    import java.util.PriorityQueue;
    
    public class Median {
        public static double median(int[] array) {
            int heapSize = array.length / 2 + 1;
            PriorityQueue<Integer> heap = new PriorityQueue<>(heapSize);
            for (int i = 0; i < heapSize; i++) {
                heap.add(array[i]);
            }
            for (int i = heapSize; i < array.length; i++) {
                if (heap.peek() < array[i]) {
                    heap.poll();
                    heap.add(array[i]);
                }
            }
            if (array.length % 2 == 1) {
                return (double) heap.peek();
            } else {
                return (double) (heap.poll() + heap.peek()) / 2.0;
            }
        }
    
        public static void main(String[] args) {
            int[] array = new int[]{12, 34, 1, 209, 17, 900, -10};
            System.out.println(median(array));
        }
    }
    
    展开全文
  • 找出无序数组中位数的方法

    千次阅读 2020-01-13 13:10:48
    今早上在LintCode上做到了这种类型的题目,题目要求找到无序数组中位数在数组的位置,一开始想到的是利用快排的思想来做,但是由于只有十五分钟的时间,就直接用最普通的方式做了,思路是map记录位置+sort排序,水...

    今早上在LintCode上做到了这种类型的题目,题目要求找到无序数组中位数在数组的位置,一开始想到的是利用快排的思想来做,但是由于只有十五分钟的时间,就直接用最普通的方式做了,思路是map记录位置+sort排序,水过去了。
    找无序数组中位数我想着我之前逛知乎的时候遇到过,用最大堆和最小堆来做的。想了想,遇到这么多次,那就整理下方法吧。

    这里中位数的定义是数组元素个数/2

    1 直接排序找中位数

    直接利用自带的sort方法排序,然后返回数组的中间索引的值
    代码如下:

        //1.直接排序
        public static int findMediaMethod1(int[] a)
        {
            if(a.length==0) return -1;
            Arrays.sort(a);
            return a[(a.length-1)/2];
        }
    

    第一种方法太暴力了,我们只需要中位数即可,而不需要对数组中所有的元素进行处理。
    这就引申出了第二种方法:

    2 利用快排思想

    快排的基本思想是选取一个哨兵元素,然后设立两个指针left,right,分别指向左端和右端,两个指针相向运动,当左右指针都遇到了违反数组次序的元素的时候左右指针交换元素(违反数组次序是指左指针找到了大于哨兵元素的元素或右指针找到了小于哨兵元素的值),这样当左右指针相遇的时候,左边的数组元素一定小于等于哨兵元素,右边的数组元素一定大于等于哨兵元素。我们可以利用这一性质来找中位数,每次进行快排操作后记录下哨兵元素的位置,如果大于中间元素的话,则我们只需要对左边进行快排操作,当小于中间元素,我们只需要对右边进行快排操作,跟二分查找很像。
    代码如下:

        //2.利用快排原理进行排序
        public static int findMediaMethod2(int[] a)
        {
            if(a.length==0) return -1;
            //中位数位置
            int mid=(a.length-1)/2;
            //左右指针位置
            int left=0,right=a.length-1;
            //进行快排操作后哨兵元素的位置
            int qsIdx=0;
            qsIdx = quickSort(left,right,a);
            while(true)
            {
                //System.out.println("qsIdx= "+qsIdx);
                if(qsIdx==mid)
                {
                    break;
                }
                else if(qsIdx<mid) qsIdx=quickSort(qsIdx+1,right,a);
                else qsIdx=quickSort(left,qsIdx-1,a);
            }
            return a[qsIdx];
        }
        public static int quickSort(int left,int right,int[] a)
        {
            int target=a[left];
            while(left<right)
            {
                while(left<right&&a[right]>=target) right--;
                a[left]=a[right];
                while(left<right&&a[left]<=target) left++;
                a[right]=a[left];
            }
            //System.out.println("left="+left);
            a[left]=target;
            return left;
        }
    

    3 利用大小堆性质

    第三种方法我是看的牛客网上的一个回答才会的。这里附上链接:
    点击这里
    大顶堆存数组中较小部分的元素,小顶堆存数组中较大部分的元素,相当于将数组分成两半了,这样
    大顶堆的堆顶或小顶堆的堆顶就是我们找的中位数。
    如何实现呢?
    1. 当插入堆中的元素个数为偶数时,将当前元素插入大顶堆,将大顶堆的堆顶元素插入小顶堆
    2. 当插入堆中的元素个数为奇数时,将当前元素插入小顶堆,将小顶堆的堆顶元素插入大顶堆
    hhh,是不是很神奇。
    代码如下:

     //3.利用大顶堆和小顶堆性质进行排序
        public static int findMediaMethod3(int[] a)
        {
            if(a.length==0) return -1;
            Queue<Integer> minHeap = new PriorityQueue<Integer>();
            Queue<Integer> maxHeap = new PriorityQueue<Integer>(new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o2-o1;
                }
            });
            for (int i=0;i<a.length;i++)
            {
                if(i%2==0)
                {
                    maxHeap.add(a[i]);
                    int top = maxHeap.poll();
                    minHeap.add(top);
                }
                else
                {
                    minHeap.add(a[i]);
                    int top = minHeap.poll();
                    maxHeap.add(top);
                }
            }
            return a.length%2==0? maxHeap.peek():minHeap.peek();
        }
    

    总结

    上面的三种方法,第一种肯定是不提倡的,第三种的话,因为一次操作就需要一次堆插入操作(log(m))(m表示堆中元素数目),n次操作的话就是nlog(m) ,第二种感觉的话应该是nlog(n)? 不过最官方的肯定是第三种方法。

    展开全文
  • 寻找无序数组中位数

    千次阅读 2017-08-06 22:13:40
    题目:求一个无序数组中位数。 如:{2,5,4,9,3,6,8,7,1}的中位数为5,{2,5,4,9,3,6,8,7,1,0}的中位数为4和5。 要求:不能使用排序,时间复杂度尽可能高 提示:考虑堆或者快排思想解决。
  • 无序数组中位数

    2021-04-04 09:27:11
    1.无序数组中位数 思路一 把无序数组排好序,取出中间的元素 时间复杂度 采用普通的比较排序法 O(N*logN) 如果采用非比较的计数排序等方法, 时间复杂度 O(N), 空间复杂度也是O(N). 思路二 (1)将前(n+1)/2个...
  • 无序数组中位数

    千次阅读 2018-12-07 16:34:46
    长度为 n 的无序数组,求中位数,如何尽快的估算出中位数,算法复杂度是多少? 算法 1(建立最小堆): 如果数组中元素有奇数个,可以采用这种算法: 步骤 1 :可以将数组的前 (n+1)//2 个元素,建立 1 个最小堆; ...
  • 思路:1、快排思想2、小顶堆或者大顶堆(使用优先级队列PriorityQueue实现小顶堆)3、top k问题可采用类似解法。...import java.util.Comparator;.../*** 无序数组中位数** 获取排序后的第size/2(size为...
  • 正如维基百科所述,中位数在理论上是o(N),但实际上并未使用,因为找到“好的”枢轴的开销太慢了。[HTTP://恩.Wikipedia.org/wiki/selection_algorithm]这是用于在数组中查找第k个元素的Quickselect算法的Java源代码...
  • 一,问题描述1,求一个无序数组中位数, (若数组是偶数,则中位数是指中间两个数字之和除以2,若数组是奇数,则中位数是指最中间位置。要求:不能使用排序,时间复杂度尽量低2, 例如:lists = [3, 2, 1, 4] , ...
  • 求一个无序数组中位数

    千次阅读 2017-08-05 14:34:09
    求一个无序数组中位数,如:{2,5,4,9,3,6,8,7,1}的中位数为5,{2,5,4,9,3,6,8,7,1,0}的中位数为4和5。 要求:不能使用排序,时间复杂度尽可能低。 解决方案一:采用堆排序思想 1、将前(n+1)/2个元素调整为一个...
  • 求一个无序数组中位数

    千次阅读 2017-08-04 23:13:05
    问题描述求一个无序数组中位数。 如:{2,5,4,9,3,6,8,7,1}的中位数为5,{2,5,4,9,3,6,8,7,1,0}的中位数为4和5。 要求:不能使用排序,时间复杂度尽可能低。 提示:考虑堆或者快排思想解决方法1:堆思路1: 分析...
  • 要解决这个问题首先要了解什仫是中位数,所谓的中位数就是在一组有序的数字中找到中间的那个数字。如果数字的个数是奇数则直接返回中间的那个数,如果数字的个数是偶数此时这组数据的中位数有两个,取中间两个数的...
  • 一、问题描述1、求一个无序数组中位数, (若数组是偶数,则中位数是指中间两个数字之和除以2,若数组是奇数,则中位数是指最中间位置。要求:不能使用排序,时间复杂度尽量低2、例如:lists = [3, 2, 1, 4] , ...
  • 1.算法题一:无序数组中位数 (快排思想O(N) 时间复杂度) package com.lightsword.leetcodeproblems import org.junit.jupiter.api.Test import java.util.* /** * 1.算法题一:无序数组中位数 (快排思想O(N) ...
  • 和求无序数组中位数。 例题: 1 . int a[] = { 12, 13, 12, 13, 19, 18, 15, 12, 15, 16, 17 },要求对数组a进行排序,要求时间复杂度为O(N) 2.求一个无序数组中位数。 如:{ 2, 5, 4, 9, 3, 6, 8, 7, 1 }的...
  • 题目:利用快排思想求一个无序数组的中位数 ...这个问题可以抽象化为寻找第k大的数,具体到寻找中位数,可分为两种情况: 如果数组长度为奇数,即为寻找第arr.length/2大的数; 如果为偶数,则为分别寻找第ar.
  • 我知道中位数的定义分按照数组长度的奇偶性分两种,但是面试官会告诉你这里求的中位数就是有序数组(len(array)+1)//2处的元素。 如: 1 2 3 4 5 6 7 8 9 的中位数是(9+1)//2 = 5 1 2 3 4 5 6 7 8 9 10 的中位...
  • 若数组有奇数个元素,中位数是a[(n-1)/2];若数组有偶数个元素,中位数为a[n/2-1]和a[n/2]两个数的平均值。这里为方便起见,假设数组为奇数个元素。 思路一:把无序数组排好序,取出中间的元素。时间复杂度取决于...
  • 无序数组中位数

    万次阅读 2009-10-15 18:53:00
    中位数即是排过序后的处于数组最中间的元素。 不考虑数组长度为偶数的情况。设集合元素个数为n。 简单的想了下: 思路1) 把无序数组排好序,取出中间的元素  时间复杂度 采用普通的比较排序法 O(N*logN)  ...
  • 来源:力扣(LeetCode) ... 题目: 给定两个大小为 m 和 n 的有序数组 ...请你找出这两个有序数组中位数,并且要求算法的时间复杂度为 O(log(m + n))。 你可以假设 nums1 和 nums2 不会同时为空。 示例 1: nu...
  • 转载:http://blog.csdn.net/zdl1016/article/details/4676882中位数即是排过序后的处于数组最中间的元素。 不考虑数组长度为偶数的情况。设集合元素个数为n。简单的想了下:思路1) 把无序数组排好序,取出中间的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,381
精华内容 4,952
关键字:

无序数组寻找中位数