无序数组找中位数

本文介绍了一种高效的方法来查找无序数组的中位数,并将其拓展到查找第k大元素的问题。通过最小堆和快速排序的partition函数实现算法,详细解释了两种思路及其背后的原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果数组长度是奇数,中位数是排序后的第(n+1)/2个元素;若是偶数,中位数是排序后第n/2个元素。

思路1:

1.1 将前(n+1)/2个元素调整为一个最小堆;
1.2 对后续每一个元素和堆顶比较,如果小于等于堆顶,丢弃之,去下一个元素。如果大于堆顶,用该元素取代堆顶,调整堆,去下一个元素重复1.2步
1.3 当遍历完所有元素之后,堆顶为中位数

思路2:

可以扩展为从无序数组中查找第k大的元素。

利用快速排序的partition函数,任意挑一个元素,以该元素key,划分数组为两部分,key左边元素小于等于key,右边元素大于等于key。在第一次partition后,如果左侧元素个数<k - 1,则在右侧子序列中递归查找;如果左侧元素个数=k-1,则第k大元素即在分点处;如果左侧元素个数>k - 1,则递归地在左侧序列中继续查找。代码如下:


public class Main {
	public static void swap(int[] a, int i, int j){
		int temp = a[i];
		a[i] =  a[j];
		a[j] = temp;
	}
	
	public static int partition(int[] arr, int low, int high){
		int pivot = arr[low];
		int i= low, j = high;
		while(i<=j){
			while(i<=j && arr[i]<=pivot)i++;
			while(i<=j && arr[j]>=pivot)j--;
			swap(arr,i,j);
		}
		swap(arr,low,j);
		return j;
	}
	//第k大的数,如果数组长度奇数,则k=(1+n)/2, 否则k=n/2
	public static int findMedian(int[] arr, int k, int low, int high){
		if(k >high -low +1) return -1;
		int pos = partition(arr,low, high);
		if(pos - low < k -1){
			return findMedian(arr, k-pos-1, pos+1, high);
		}else if(pos - low == k-1){
			return arr[pos];
		}else {
			return findMedian(arr, k, low, pos-1);
		}
	}
	
	
	public static void main(String[] args) {
		int[] arr= {3,5,2,3,5,9,1,2,11,12,13};
		int res = 0;
		if(arr.length%2 ==1){
			res = findMedian(arr, (arr.length+1)/2, 0, arr.length-1);
		}else{
			res = findMedian(arr, arr.length/2, 0, arr.length-1);
		}
		System.out.println(res);
	}

}


Java中,可以使用PriorityQueue来实现无序数组中位数。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在Java中,可以使用PriorityQueue来实现无序数组中位数。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)); } } ``` 其中,首先定义了一个大小为数组长度一半加一的最小堆,然后将数组的前一半元素加入堆中。接着,遍历数组的后一半元素,如果当前元素比堆顶元素大,则将堆顶元素弹出,将当前元素加入堆中。最后,如果数组长度奇数,则中位数就是堆顶元素;如果数组长度为偶数,则中位数就是堆顶元素和次顶元素的平均值。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值