有序数组中找中位数

问题描述

给定两个有序数组,返回这两个数组的中位数。如果中位数有两个,则返回它们的平均值。

e.g. [1, 3, 5]和[2, 4, 6]的中位数是3.5

 

解决思路

如果两个数组的长度之和为奇数,则中位数有一个;否则中位数为其中两个的平均值。

从两个数组中找第k个数,可以使用递归的思路。

 

程序

首先,写出在有序数组a和b中找到第k大的程序:

1. 利用归并排序中的merge数组方法,时间复杂度为O(k)。

	public int findKthNaive(int[] a, int[] b, int k) {
		int p1 = 0, p2 = 0;
		int i = 0;

		while (p1 < a.length && p2 < b.length) {
			if (i == k - 1) {
				return Math.min(a[p1], b[p2]);
			}
			if (a[p1] < b[p2]) {
				++p1;
			} else {
				++p2;
			}
			++i;
		}

		if (p1 == a.length) {
			return b[k - a.length - 1];
		}
		if (p2 == b.length) {
			return a[k - b.length - 1];
		}

		return -1;
	}

 

2. 如果两个数组的长度分别为m和n,则下面方法的时间复杂度为O(log(m+n)).

	public int findKthElemRec(int[] a, int a_start, int[] b, int b_start, int k) {
		if (a_start >= a.length) {
			return b[b_start + k - 1];
		}
		if (b_start >= b.length) {
			return a[a_start + k - 1];
		}

		if (k == 1) {
			return Math.min(a[a_start], b[b_start]);
		}

		int a_mid = a_start + k / 2 - 1 < a.length ? a[a_start + k / 2 - 1]
				: Integer.MAX_VALUE;
		int b_mid = b_start + k / 2 - 1 < b.length ? b[b_start + k / 2 - 1]
				: Integer.MAX_VALUE;

		if (a_mid < b_mid) {
			return findKthElemRec(a, a_start + k / 2, b, b_start, k - k / 2);
		} else {
			return findKthElemRec(a, a_start, b, b_start + k / 2, k - k / 2);
		}
	}

 

找中位数的程序只需要调用2即可

	public double findMedian(int[] a, int[] b) {
		int len1 = a == null ? 0 : a.length;
		int len2 = b == null ? 0 : b.length;
		int len = len1 + len2;
		
		if (len % 2 == 0) {
			return (findKthElemRec(a, 0, b, 0, len / 2) + findKthElemRec(a, 0,
					b, 0, len / 2 + 1)) / 2.0;
		} else {
			return findKthElemRec(a, 0, b, 0, len / 2 + 1);
		}
	}

  

posted @ 2015-07-12 15:57  Chapter  阅读(333)  评论(0编辑  收藏  举报