从俩个有序数组中找出第K小的数。要求时间复杂度O(logmin(m,n))
2017-08-25 21:23
288 查看
思路
该题目要求时间复杂度为O(log(min{m,n})) 所以不能直接遍历任意一个数组这样时间复杂度就不符合了。也不能对任意一数组进行二分查找,因为要求是俩个数组元素合并后的第K小的数,所以直接遍历用二分遍历任意一个数组也是行不通的。 故我们可以以区间的方式解决这个问题。我们先假设第一个数组个数小于等于第二个数组个数。如果不是则交换俩个数组即可。这样的话,先定义俩个区间,第一个区间range大小为min(2/k,len1),这个区间最大为k/2,最小为1.第二个区间就是K-range大小。 我们可以通过查看第一个区间的最后一个元素和第二个区间的最后一个元素的值大小来缩短区间最终找到第k个元素这分三种情况: 1.如果第一个区间最后一个元素的值等于第二个区间最后一个元素的值。那么区间的最后一个元素就是第k个元素。因为这俩个区间个数加起来等于k,并且这俩个区间值又是相等的,那么说明我们筛选出来了前K小的元素区间,所以最后一个元素是第k小的元素。 2.如果第一个区间最后一个元素值比第二个区间最后一个元素值小。那么说明第一个区间所有元素都是前k小区间元素中的元素。所以我们可以继续遍历,此时不在查找第k小个数了,更新到了查找第k-range1小的数了。那么我们可以缩短第一个数组,第二个数组不变继续遍历。 3.如果第二个区间最后一个元素值比第义个区间最后一个元素值小。那么说明第二个区间所有元素都是前k小区间元素中的元素。所以我们可以继续遍历,此时不在查找第k小个数了,更新到了查找第k-range2小的数了。那么我们可以缩短第二个数组,第一个数组不变继续遍历。 那么当有一个数组个数被筛选的缩短至0时,答案就出来了,此时第k个元素必定在第二个数组直接就可以找到了。 如果k缩小到1了,答案也出来了,那就是俩个缩短后的数组中的首元素的较小值为第k个元素。 所以这就是以上思路。
代码
int FindKthNum(int * arr1, int len1, int*arr2, int len2, int kth) { assert(arr1 != NULL&&arr2 != NULL); assert(len1 + len2 > kth); if (kth == 1) return min(arr1[0], arr2[0]); if (len1 > len2) return FindKthNum(arr2, len2, arr1, len1, kth); if (len1 == 0) return arr2[kth];//为了后续递归时,如果第一个区间筛选完了,那么结果肯定就在第二个区间了 int range = std::min(len1, kth / 2); int range2 = kth - range; if (arr1[range - 1] == arr2[range2 - 1]) return arr1[range - 1]; if (arr1[range - 1] < arr2[range2 - 1]) return FindKthNum(arr1 + range, len1 - range, arr2, len2, kth - range); if (arr2[range2 - 1] < arr1[range - 1]) return FindKthNum(arr1, len1, arr2+range2, len2 - range2, kth - range2); }
相关文章推荐
- 找出大数组array中第k大的元素(要求时间复杂度O(1))
- 找出和值等于指定值的元素,如有序数组{1,2,6,23,43,64},求和等于25的两个和数则将是元素2和23,时间复杂度是0(n)。
- 一个整型数组里除了一个或者两个或者三个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)
- 给定一个乱序数组,找到其中第K大的值,要求时间复杂度最低
- (最优解)阿里笔试题请设计一个算法,在满足质因数仅为3,5,7或其组合的数中,找出第K大的数。比如K=1,2,3时,分别应返回3,5,7。要求算法时间复杂度最优。
- 人人都来写算法 之 归并有序数组,(要求:利用原数组,且时间复杂度O(n)
- 一个整型数组里除了一个或者两个或者三个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)
- 同时找出数组的最大值和最小值,要求时间复杂度为o(n)
- 一个整型数组里除了一个或者两个或者三个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)
- 找出数组中第k大的数(时间复杂度分析、C++代码实现). TopK in array. ( leetcode - 215 )
- 一个整型数组里除了一个数字之外,其他的数字都出现了两次。要求时间复杂度是O(n),空间复杂度是O(1),如何找出数组中只出现一次的数字
- 找出一个数组中出现次数超过一半的那个数字,要求时间复杂度O(n)和空间复杂度为O(1)。
- 在一个数组中,除了两个数外,其余数都是两两成对出现,找出这两个数,要求时间复杂度O(n),空间复杂度O(1)
- 写一个功能函数实现从数组中找出两个值相加等于某一个值,要求时间复杂度为 n;
- 在旋转后的有序数组中查找元素,要求O(logn)的时间复杂度
- 一个整型数组里除了两个数字之外,其他的数字都出现了两次。 请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n), 空间复杂度是O(1)
- 一个数组中,存在两个只出现一次的数字,其余的数字均出现两次。要求在时间复杂度o(n),空间复杂度为o(1)的情况下找出这两个数字
- 有1,2,....一直到n的无序数组,求排序算法,要求时间复杂度为O(n),空间复杂度O(1)
- 把一个数组向右循环移动k位要求时间复杂度为O(n)
- 在已排序的数组中寻找和是给定值的两项,要求时间复杂度为O(n)