`
eriol
  • 浏览: 405492 次
  • 性别: 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长度为...

    两个有序数组求交集,C++

    ### 两个有序数组求交集(C++) 在计算机科学领域,处理数组的交集问题是一项基本而重要的任务。本文将详细介绍如何使用C++语言来实现两个有序数组的交集操作,并深入探讨其背后的原理和算法优化策略。 #### 1. 问题...

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

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

    c语言编程题之数组操作合并两个有序数组.zip

    在上述代码中,`merge`函数实现了合并两个有序数组的功能。`printArray`函数用于打印数组,方便我们验证结果。`main`函数中定义了两个有序数组,并调用`merge`函数进行合并,最后输出合并后的数组。 通过这个编程题...

    凯撒密码合并两个有序数组

    合并两个有序数组是指,给定两个已排序的整数数组arr1和arr2,我们需要创建一个新的数组,该数组包含两个输入数组的所有元素,并且仍然保持排序顺序。 ### 算法步骤: 1. 初始化三个指针:`i` 对应于 `arr1` 的...

    前端JS合并两个有序数组,快速搞定!

    在合并两个有序数组时,我们希望保持合并后的数组依然有序。一种直观的方法是遍历两个数组,比较每个元素,然后将较小的元素添加到新数组中。这种方法虽然简单,但效率较低,时间复杂度为 O(n*m),其中 n 和 m 分别...

    C++实现两个有序数组的合并

    在本篇文章中,我们将详细介绍如何使用C++语言实现两个有序数组的合并。数组合并是数据结构和算法中的一种常见操作,掌握数组合并的技巧对于提高编程技能非常重要。 数组合并的概念 数组合并是指将两个或多个数组...

    java-leetcode题解之第88题合并两个有序数组.zip

    标题中的“java-leetcode题解之第88题合并两个有序数组”指的是LeetCode平台上的一个编程挑战,问题编号为88,它涉及到如何合并两个已排序的整数数组,使得结果仍然保持有序。LeetCode是一个热门的在线编程练习平台...

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

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

    php-leetcode题解之合并两个有序数组.zip

    在本压缩包“php-leetcode题解之合并两个有序数组.zip”中,主要涉及的是一个经典的算法问题——如何使用PHP解决LeetCode上的“合并两个有序数组”问题。这是一个常见的计算机科学与编程面试题目,旨在考察程序员...

    合并两个有序数组1

    合并两个有序数组是计算机科学中一个常见的操作,特别是在数据结构和算法的学习中。这个任务主要涉及到数组的操作和排序。在LeetCode中,这个问题被称为“合并两个有序数组1”(Merge Two Sorted Arrays)。以下是对...

    python 两个排序数组的中位数

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

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

    我们需要在两个有序数组中找到中位数,确保算法的时间复杂度为 O(log(min(m, n)))。 解题思路 确保第一个数组较小:始终在较小的数组上进行二分查找,以确保时间复杂度最优。 进行二分查找: 定义分割点 i 在 nums1...

    合并两个有序数组(java代码).docx

    ### 合并两个有序数组(Java代码) #### 知识点概述 本篇文章主要介绍了一种使用Java语言来实现合并两个有序整数数组的方法。在实际应用中,尤其是在数据处理和算法设计领域,有序数组的合并是一个非常实用且常见...

    java-leetcode面试题解双指针之第88题合并两个有序数组.zip

    总之,本压缩包中的资源提供了针对LeetCode第88题的Java解法,该题主要涉及双指针技术在合并两个有序数组问题上的应用。学习和理解这种解法,不仅能提升你在算法方面的技能,也有助于你在实际工作中的问题解决能力。

    高效合并两个有序数组.py

    输入参数nums1和nums2分别为两个数组,m和n表示nums1中待处理部分的长度和nums2的剩余长度。函数的核心是while循环,条件是两个数组还有元素未合并。 循环内部的判断是根据两个数组当前末尾元素的大小来决定将哪个...

    python-leetcode面试题解之第88题合并两个有序数组-题解.zip

    在本压缩包中,我们关注的是一个Python编程与算法相关的面试题目,具体是LeetCode的第88题:合并两个有序数组。这是一个经典的算法问题,对于准备Python编程岗位的求职面试来说,掌握这类问题的解决方案至关重要。...

Global site tag (gtag.js) - Google Analytics