algorithm@ find kth smallest element in two sorted arrays (O(log n time)
The trivial way, O(m + n):
Merge both arrays and the k-th smallest element could be accessed directly. Merging would require extra space of O(m+n). The linear run time is pretty good, but could we improve it even further?
A better way, O(k):
There is an improvement from the above method, thanks to readers who suggested this. (See comments below by Martin for an implementation). Using two pointers, you can traverse both arrays without actually merging them, thus without the extra space. Both pointers are initialized to point to head of A and B respectively, and the pointer that has the larger finding intersection of two sorted arrays.
The best solution, but non-trivial, O(lg m + lg n):
Although the above solution is an improvement both in run time and space complexity, it only works well for small values of k, and thus is still in linear run time. Could we improve the run time further?
The above logarithmic complexity gives us one important hint. Binary search is a great example of achieving logarithmic complexity by halving its search space in each iteration. Therefore, to achieve the complexity ofO(lg m + lg n), we must halved the search space of A and B in each iteration.
We try to approach this tricky problem by comparing middle elements of A and B, which we identify as Ai and Bj. If Ai is between Bj and Bj-1, we have just found the i + j< + 1
smallest element. Why? Therefore, if we choose i and j such that i + j = k - 1
, we are able to find the k-th smallest element. This is an important invariant that we must maintain for the correctness of this algorithm.
Summarizing the above,
i + j = k - 1,
If Bj-1 < Ai < Bj, then Ai must be the k-th smallest,
or else if Ai-1 < Bj < Ai, then Bj must be the k-th smallest.
If one of the above conditions are satisfied, we are done. If not, we will use i and j as the pivot index to subdivide the arrays. But how? Which portion should we discard? How about Ai and Bj itself?
We make an observation that when Ai < Bj, then it must be true that Ai < Bj-1. On the other hand, if Bj < Ai, then Bj < Ai-1. Why?
Using the above relationship, it becomes clear that when Ai < Bj, Ai and its lower portion could never be the k-th smallest element. So do Bj and its upper portion. Therefore, we could conveniently discard Ai with its lower portion and Bj with its upper portion.
If you are still not convince why the above argument is true, try drawing blocks representing elements in A and B. Try visualize inserting blocks of A up to Ai in front of Bj-1. You could easily see that no elements in the inserted blocks would ever be the k-th smallest. For the latter, you might want to keep the invariant i + j = k - 1 in mind to reason why Bj and its upper portion could never be the k-th smallest.
On the other hand, the case for Ai > Bj is just the other way around. Easy.
Below is the code and I have inserted lots of assertion (highly recommended programming style by the way) to help you understand the code. Note that the below code is an example of tail recursion, so you could technically convert it to an iterative method in a straightforward manner. However, I would leave it as it is, since this is how I derive the solution and it seemed more natural to be expressed in a recursive manner.
Another side note is regarding the choices of i and j. The below code would subdivide both arrays using its array sizes as weights. The reason is it might be able to guess the k-th element quicker (as long as the A and B is not differed in an extreme way; ie, all elements in A are smaller than B). If you are wondering, yes, you could choose i to be A's middle. In theory, you could choose any values for i and j as long as the invariant i+j = k-1 is satisfied.
- int findKthSmallest(int A[], int m, int B[], int n, int k) {
- assert(m >= ); assert(n >= ); assert(k > ); assert(k <= m+n);
- int i = (int)((double)m / (m+n) * (k-));
- int j = (k-) - i;
- assert(i >= ); assert(j >= ); assert(i <= m); assert(j <= n);
- // invariant: i + j = k-1
- // Note: A[-1] = -INF and A[m] = +INF to maintain invariant
- int Ai_1 = ((i == ) ? INT_MIN : A[i-]);
- int Bj_1 = ((j == ) ? INT_MIN : B[j-]);
- int Ai = ((i == m) ? INT_MAX : A[i]);
- int Bj = ((j == n) ? INT_MAX : B[j]);
- if (Bj_1 < Ai && Ai < Bj)
- return Ai;
- else if (Ai_1 < Bj && Bj < Ai)
- return Bj;
- assert((Ai > Bj && Ai_1 > Bj) ||
- (Ai < Bj && Ai < Bj_1));
- // if none of the cases above, then it is either:
- if (Ai < Bj)
- // exclude Ai and below portion
- // exclude Bj and above portion
- return findKthSmallest(A+i+, m-i-, B, j, k-i-);
- else /* Bj < Ai */
- // exclude Ai and above portion
- // exclude Bj and below portion
- return findKthSmallest(A, i, B+j+, n-j-, k-j-);
- }
algorithm@ find kth smallest element in two sorted arrays (O(log n time)的更多相关文章
- 查找两个有序数组中的第K个元素(find kth smallest element in 2 sorted arrays)
查找两个有序数组中的第K个元素 int FindKth(int a[], int b[], int k, int astart, int aend, int bstart, int bend) { ; ...
- Leetcode:378. Kth Smallest Element in a Sorted Matrix
题目: Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the ...
- [LeetCode] Kth Smallest Element in a Sorted Matrix 有序矩阵中第K小的元素
Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth ...
- 378. Kth Smallest Element in a Sorted Matrix
Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth ...
- Leetcode: Kth Smallest Element in a Sorted Matrix
Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth ...
- [Swift]LeetCode378. 有序矩阵中第K小的元素 | Kth Smallest Element in a Sorted Matrix
Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth ...
- 【Leetcode】378. Kth Smallest Element in a Sorted Matrix
Question: Given a n x n matrix where each of the rows and columns are sorted in ascending order, fin ...
- Kth Smallest Element in a Sorted Matrix -- LeetCode
Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth ...
- leetcode_378. Kth Smallest Element in a Sorted Matrix_堆的应用
Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth ...
随机推荐
- 建立Clojure开发环境-使用IDEA和Leiningen
OS: Mac OS X 10.10 IDEA 14.0.2 Community Edition 安装Leiningen 按照http://leiningen.org/的指南安装lein 阅读Lein ...
- 使用Web代理实现Ajax跨域
目前的工作项目分为前端和后台,双方事先约定接口,之后独立开发.后台每天开发完后在测试服务器上部署,前端连接测试服务器进行数据交互.前端和后台分开的好处是代码不用混在一个工程里一起build,互不干涉. ...
- STL,ATL,WTL之间的联系和区别
STL即 Standard Template Library (标准模板库) STL是惠普实验室开发的一系列软件的统称.它是由Alexander Stepanov.Meng Lee和David R M ...
- POJ2526+简单几何
题意:给定的这些点是否有一个对称中心. PS:我写得有点啰嗦.. 就是把小的x和大的x进行匹配. #include<stdio.h> #include<algorithm> # ...
- 常用的富文本框插件FreeTextBox、CuteEditor、CKEditor、FCKEditor、TinyMCE、KindEditor ;和CKEditor实例
http://www.cnblogs.com/cxd4321/archive/2013/01/30/2883078.html 目前市面上用的比较多的富文本编辑器有: FreeTextBox 一个有很多 ...
- java中 正则表达式的使用
推荐使用第一种 第一种: //对接收的文件名的合法性进行验证 String fileName="127.0.0.1_01_20140428165022174.jpg"; Strin ...
- POJ2993——Help Me with the Game(字符串处理+排序)
Help Me with the Game DescriptionYour task is to read a picture of a chessboard position and print i ...
- UPDATE和SELECT嵌套使用
1 2 update a set HIGH=b.NEW from SPEC1 a,tmpDOT b where a.high=b.old
- 安装Hadoop系列 — 新建MapReduce项目
1.新建MR工程 依次点击 File → New → Ohter… 选择 “Map/Reduce Project”,然后输入项目名称:mrdemo,创建新项目: 2.(这步在以后的开发中可能 ...
- PHP判断日期是不是今天 判断日期是否为当天
<?php /** * PHP判断一个日期是不是今天 * 琼台博客 */ echo '<meta charset="utf-8" />'; // 拟设一个日期 $ ...