`
eriol
  • 浏览: 400131 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

在两个有序数组中找第N数

阅读更多

给定两个有序的数组,长度分别为m和n,求这两个数组中的第K个元素。

 

 

问题分析:

 

1. 把 A 平均分为前后两个部分,前部分有 x 个元素,后部分有 n-x 个元素(由于 A 是有序的,所以后一部分的所有元素都大于前一部分)。A[x] 为 A 的后一部分中的第一个元素。

 

2. 同理把 B 也平均分成前后两个部分,前部分有 y 个元素,后部分有 m-y 个元素。B[y] 是 B 的后一部分中的第一个元素。

 

3. 由于两个数组都是被平均分割的,所以可以近似地认为 x = n/2, y = m/2。这里不妨设 A[x] <= B[y](如果 A[x] > B[y] 处理过程和下面类似): 

 

 

情况1:

 

由于在 A 中,A[x] 前面有 x 个元素,在 B 中,B[y] 前面有 y 个元素,并且又有 A[x] <= B[y],那么,合并以后,A[x]前面原来那些元素必然也在B[y]前面。也就是说,B[y]前面至少会有 x + y 个元素,我们再规定如果 A, B 中有相同元素,则合并后 A 中的元素排在 B 前面,那么归并以后 A[x] 也会排在 B[y] 前面,于是,合并之后 B[y] 至少有 x+y+1 个元素。 

 

如果 k <= x+y+1,也就是说,合并后第 k 个元素必然落在 B[y] 前面。所以,原来在 B 数组中的后一部分(B[y]以及 B[y] 之后)那些元素都不可能包含我们要找到内容(第 k 大元素),所以我们可以把他们排除掉。这样就排除了 B 中一半的内容。 

 


情况2:

 

在 A 中,A[x] 及其后面有 n-x 个元素,除去 A[x] 之后有 n-x-1 个元素,B[y] 及其后面有 m-y 个元素。那么,由于 A[x] <= B[y],所以合并起来之后,B[y] 后面那些元素必然也在 A[x] 后面,则合并后 A[x] 后面至少有(n-x-1) + (m-y) = (n+m)-(x+y+1) 个元素。 

 

如果 k > x+y+1,也就说,合并后第 k 大的元素必然落在 A[x] 后面。所以,原来在 A 数组中,第一部分(A[x]之前)以及 A[x] 都不可能包含我们要找的元素,所以我们可以把他们排除掉。这样就排除了 A 中一半的内容。 

 

 

总结:

 

综上所述,对于 k <= x+y+1 还是 k > x+y+1 我们都提出了解决的方案,并且每种方案都能把 A 或者 B 的规模减小一半。减小了一半之后,我们将其作为一个新的问题继续使用上面的算法处理,直到 A 或者 B 减小到足够小: 

  1. A 没有了,这样只需要找出 B 中第 k 大的元素,也就是 B[k]。
  2. B 没有了,同上结果就是 A[k]。

public class NumX {

	private int[] a;
	private int[] b;
	
	public int find(int aLeft, int aRight, int bLeft, int bRight, int k) {
		int aMid = (aLeft + aRight) / 2;
		int bMid = (bLeft + bRight) / 2;
		
		if (aLeft > aRight)
			return b[bLeft+k-1];
		if (bLeft > bRight)
			return a[aLeft+k-1];
		
		if (a[aMid] <= b[bMid]) {
			if (k <= (aMid-aLeft) + (bMid-bLeft) + 1)
				return find(aLeft, aRight, bLeft, bMid-1, k);
			else
				return find(aMid+1, aRight, bLeft, bRight, k-(aMid-aLeft)-1);
		} else {
			if (k <= (aMid-aLeft) + (bMid-bLeft) + 1)
				return find(aLeft, aMid-1, bLeft, bRight, k);
			else
				return find(aLeft, aRight, bMid+1, bRight, k-(bMid-bLeft)-1);
		}
	}
	
	public static void main(String[] args) {
		NumX n = new NumX();
		n.a = new int[] {1, 4, 6};
		n.b = new int[] {5, 8, 9};
		System.out.println(n.find(0, 2, 0, 2, 3));
	}
}

 

 

原文地址:http://blog.csdn.net/linandixon/article/details/4647392

分享到:
评论

相关推荐

    C++算法:寻找两个有序数组的中位数

    请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。 你可以假设 nums1 和 nums2 不会同时为空。 示例 1: nums1 = [1, 3] nums2 = [2] 则中位数是 2.0 示例 2: nums1 = [1, 2] ...

    分治法求两列有序数组的中位数的程序

    (1)设X[0:n-1]和Y[0:n-1]为两个数组,每个数组中含有n个已排好序的数,设计一个算法复杂度为O(logn)的分治算法,找出X和Y中2n个数中的中位数。(中位数:个数为奇数:中间位置上的数;个数为偶数,中间两个数的...

    17082 两个有序数序列中找第k小

    17082 两个有序数序列中找第k小(必做) 时间限制:1000MS 内存限制:65535K 提交次数:0 通过次数:0 题型: 编程题 语言: C++;C;VC;JAVA Description 已知两个已经排好序(非减序)的序列X和Y,其中X的长度为m,Y长度为...

    ZYZMZM#LeetCode#4. 寻找两个有序数组的中位数1

    4. 寻找两个有序数组的中位数给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O

    算法/编程练习:两个有序数组的中位数

    找出这两个有序数组的中位数mid。 要求算法的时间复杂度为 O(log(m + n))。 例如, 输入: nums1 = [1, 3, 5, 7, 9], nums2 = [2, 4, 6, 8, 10, 11] 输出: mid=6 思路: 记总的数组长度为 N = n1 + n2,则两个数组...

    python 两个排序数组的中位数

    # 请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log (m+n)) # 你可以假设 nums1 和 nums2 不同时为空 # 示例 1: # nums1 = [1, 3] # nums2 = [2] # 中位数是 2.0 # 示例 2: # nums1 = [1, 2] # nums2 ...

    两个有序数序列中找第k小(必做)

    已知两个已经排好序(非减序)的序列X和Y,其中X的长度为m,Y长度为n, 现在请你用分治算法,找出X和Y的第k小的数,算法时间复杂度为O(max{logm, logn})。

    寻找两个有序数组的中位数

    请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。 你可以假设 nums1 和 nums2 不会同时为空。 示例1: nums1 = [1, 3] nums2 = [2] 则中位数是 2.0 示例2: nums1 = [1, 2] nums...

    Python寻找两个有序数组的中位数实例详解

    Python寻找两个有序数组的中位数 审题: 1.找出意味着这是一个查找算法题 2.算法复杂度log级别,就是提示你是二分查找 3.二分查找实现一般为递归  (1)递归包括递归体  (2)终止条件 思路: 定理: 1.有序数组...

    leetcode无法登录-0004.findMedianSortedArrays:两个有序数组的中位数

    无法登录两个有序数组的中位数 LeetCode 中“无重复字符的最长子串”问题的解决方法。 问题 有两个大小分别为 m 和 n 的排序数组 nums1 和 nums2。 找出两个已排序数组的中位数。 整体运行时间复杂度应该是 O(log (m...

    JavaScript实现获取两个排序数组的中位数算法示例

    请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log (m+n)) 。 你可以假设 nums1 和 nums2 不同时为空。 示例 1: nums1 = [1, 3] nums2 = [2] 中位数是 2.0 示例 2: nums1 = [1, 2] nums2 = [3, 4...

    给一个整数数组,找到两个数使得他们的和等于一个给定的数 target。输出这两个数的下标, 并且第一个下标小于第二个下标。注意这里下标的范围是 0 到 n-1。你可以假设数组递增有序,O(N)时间完成

    你需要输出这两个数的下标, 并且第一个下标小于第二个下标。注意这里下标的范围是 0 到 n-1。 你可以假设数组递增有序。 请在O(N)时间内完成。 输入 第一行:N个整数,作为数组的元素,空格分开 第二行:target 输出...

    数据结构 二分查找 上机实验

    编写Search_Bin函数,实现在一个递增有序数组ST中采用折半查找法确定元素位置的算法. Input 第一行:元素个数n 第二行:依次输入n个元素的值(有序) 第三行:输入要查找的关键字key的值 Output 输出分两种情形:...

    leetcode4. 寻找两个有序数组的中位数

    还是暴力法,不过不用新数组,而是用两个指针和一个变量来求第k小的数,k=(m+n)/2 3.用二分法来求第k小的数,如果m+n是偶数,则求第k和第k+1小的平均值。 */ class Solution { public double ...

    LeeCode每日一题–合并两个有序数组

    合并两个有序数组    题目描述:给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 num1 成为一个有序数组。    说明:      初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。  ...

    求两个等长有序序列的中位数_nonewqq_数据结构_

    实现了求两个等长数组中位数的算法,利用C++语言实现

    用递归和非递归两种方式实现归并排序

    具体来说,假设待合并的两个有序数组分别为A和B,它们的长度分别为n和m,合并后的有序数组为C,那么合并的过程可以按如下步骤进行: 1. 定义三个指针i、j和k,分别指向数组A、B和C的起始位置。 2. 比较A[i]和B[j]的...

    leetcode下载-Algorithm:算法题积累

    在一个有序数组中,判断一个数是否存在 Q6 二分法 在一个有序数组中,找&gt;= 某个数最左侧的位置 Q7 二分法 在一个有序数组中,找&lt;=某个数最右侧的位置 Q8 二分法 局部最小值的问题: 在一个无序数组中,任意相邻两...

    10道python编程经典考试面试题目(附加代码)

    Python在编程试题和面试中有许多经典题目和...合并两个有序数组:将两个有序数组合并成一个有序数组。 二叉树遍历:实现二叉树的前序、中序和后序遍历。 斐波那契数列:编写一个函数来生成斐波那契数列的前n个数字。

    LeetCode刷题笔记——#88. 合并两个有序数组

      如此一来,设置三个指针,只需要把当前合适的数放到额外空间中。   由于比较,总会有一个数组先结束,对于后结束的一个数组,如果其恰好就是最终需要返回的,则无需处理。   如果是另一个数组,则直接把它的...

Global site tag (gtag.js) - Google Analytics