两个排序数组的中值 --- 线性表

【描述】

有两个大小分别为m和n的排序数组A和B,找到两个排序的中间值数组。总体运行时复杂度应该为O(log(m + n));

【分析】

这是一道很不错的例题,就如给定两个已经排序好的数组,找到两者所有元素中的第k大的元素;

O(m+n)的算法比较只管,直接merge两个数组,然后求第k大的元素。

不过只是需要第K大的元素,没有必要进行排序求取。可以使用一个计数器和两个指针就可以解决,此处就不进行详细解说(如果想知道详细思路,请评论区留言)。寻找较优算法,我们可以从k出发。还有一点,我们应该充分利用已知信息 - “有序”,所以可以考虑二分法;

假设数组A 和 数组B 的元素个数都大于k/2,我们将A的第k/2个元素 和 B的k/2个元素进行比较,情况如下:

情况一:A[K/2 - 1] < B[K/2 -1];

情况二:A[K/2 - 1] == B[K/2 -1];

情况三:A[K/2 - 1] > B[K/2 - 1];

如果属于情况一,意味着A[0] ~ A[K/2 - 1]的元素值 肯定 在 A 和B元素总和的top k元素的范围内(如有不相信,可以自证);

因此,可以删除A数组的这k/2个元素。同理,如果属于情况三,可以删除B数组的k/2个元素。

当属于情况二时,说明已经找元素,直接返回任意一个值。

注意: 

【代码实现】

注意:需要测试用例,评论留言;

//demo.h
int findMidSortedArrs(int A[], int m, int B[], int n);
//demo.c
#include "demo.h"

int myMin(int a, int b)
{
	return a > b ? b : a;
}

static int findKth(int A[], int m, int B[], int n, int k)
{
	if (m > n) {
		return findKth(B, n, A, m, k);
	}
	if (m == 0) {
		return A[k - 1];
	}
	if (k == 1) {
		return myMin(A[0], B[0]);
	}

	int ia = myMin(k/2, m), ib = k - ia;
	if (A[ia - 1] < B[ib - 1]) {
		return findKth(A + ia, m - ia, B, n, k - ia);
	}
	else if (A[ia - 1] > B[ib - 1]) {
		return findKth(A, m, B + ib, n - ib, k - ib);
	}
	else {
		return A[ia - 1];
	}
}

int findMidSortedArrs(int A[], int m, int B[], int n)
{
	int total = m + n;
	if (total % 2 != 0) {
		return findKth(A, m, B, n, total / 2 + 1);
	}
	else {
		return (findKth(A, m, B, n, total / 2)
				+ findKth(A, m, B, n, total / 2 + 1));
	}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值