【问题标题】:An algorithm to find the nth largest number in two arrays of size n在大小为 n 的两个数组中找到第 n 个最大数的算法
【发布时间】:2013-01-26 10:12:31
【问题描述】:

我有这个问题:

给定两个大小为 n 的排序列表(存储在数组中),求 O(log n) 计算并集中第 n 个最大元素的算法 两个列表。

我可以看到这里可能有一个技巧,因为它需要第 n 个最大的元素,并且数组的大小也是 n,但我不知道它是什么。我在想我可以适应计数排序,这行得通吗?

【问题讨论】:

  • 2 个列表的并集如何工作?
  • @Gumbo:如果数组大小 > n,并假设“2 个列表的并集”只是意味着将所有列表放在一起,那么我们总是可以将数组修剪为大小 n(由于排序的属性)。
  • O(n) 是天真的方法:只需比较 2 个列表中的最小元素,推进指针并计数。
  • 如果数组是排序的不相交的那么它可能在O(log n)(我在考虑二进制搜索)。否则 - 没有机会。
  • @Joe:你能回答我的第一个问题吗?我们很困惑union在这里是指集合的联合,它删除重复元素,还是只是将两个列表放在一起?

标签: algorithm language-agnostic


【解决方案1】:

比较 A[n/2] 和 B[n/2]。如果相等,它们中的任何一个都是我们的结果。该算法的其他停止条件是当两个数组的大小均为 1 时(最初或在几个递归步骤之后)。在这种情况下,我们只选择 A[n/2] 和 B[n/2] 中的最大值。

如果 A[n/2]

如果 A[n/2] > B[n/2],则递归地对 B[] 的后半部分和 A[] 的前半部分重复此过程。

由于每一步问题大小(在最坏的情况下)减半,我们将得到 O(log n) 算法。


只有当 n 是 2 的幂时,总是将数组大小除以 2 才能使索引正常工作。选择索引的更正确方法(对于任意 n)是对一个数组使用相同的策略,但为另一个数组选择补充索引:j=n-i

【讨论】:

  • 您将如何处理{1}、{2}的情况?
  • 好的,我明白了。现在你提到它很明显。感谢大家的帮助。
  • 就像 nhahtdh 提到的那样,您在答案中得到了主要思想,但您必须跟踪到目前为止您丢弃了多少元素,以便知道当您的长度不均匀时如何拆分列表并最终选择当剩余列表包含 1 个单个值时,选择好的。
  • 根据 nhahtdh 和 Rerito 的建议,更新后的答案阐明了该算法。
  • 总是dividing the array size by 2 works in general casen 不一定是 2 的幂。
【解决方案2】:

Evgeny Kluev 给出了一个更好的答案——我的答案是 O(n log n),因为我不认为它们是经过排序的。

我可以添加的是一个非常好的视频的链接,该视频解释了二进制搜索,由 MIT 提供:

https://www.youtube.com/watch?v=UNHQ7CRsEtU

【讨论】:

  • 将 2 个排序列表放在一个排序列表中需要 O(n)。
  • 他可以选择不连接它们并在两者之间进行迭代。以及从摊销的角度来看待这一点。这取决于你如何实现这一点。他不知道这些列表是否包含它们可能的重复。可能我还是错了,也许他根本不需要连接它们。
  • 我现在看到我的逻辑是 O(n log n),我将编辑我的帖子以反映这一点。
  • @Shokodemon:你知道 O(n log n) 比遍历两个数组的正常方式更差,最多产生 O(n)。
  • 是的,我的错是我没有很好地阅读这个问题,抱歉。
【解决方案3】:
public static void main(String[] args) {  


int[] fred = { 60, 5, 7, 3, 20, 3, 44 };  

int[] tmp = new int[fred.length];  
go(fred, 1, tmp, 3);  
}  

public static void go(int[] fred, int cnt, int[] tmp, int whatPosition) {  
int max = 0;  
int currentPosition = 0;  
for (int i = 0; i < fred.length; i++) {  
if (i == 0)  
max = fred[i];  
else {  
if (fred[i] > max) {  
max = fred[i];  
currentPosition = i;  
}  
}  
}  
System.arraycopy(fred, 0, tmp, 0, fred.length);  
tmp[currentPosition] = 0;  
cnt++;  
if(cnt != whatPosition)  
go(tmp, cnt, tmp, whatPosition);  
else{  
for (int i = 0; i < tmp.length; i++) {  
if (i == 0)  
max = tmp[i];  
else {  
if (tmp[i] > max) {  
max = tmp[i];  
}  
}  
}  
System.out.println(max);  
}  




}  

【讨论】:

    猜你喜欢
    • 2012-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-29
    • 2012-01-06
    相关资源
    最近更新 更多