- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
最近我参加了一个面试,被问了一个问题。
我有 2 套,每套大约有 100 万条记录。我必须找到 2 个集合中的公共(public)元素。
我的回复:
我将创建一个新的空集合。我给了他下面的解决方案,但他对此并不满意。他说有 100 万条记录,所以解决方案不会很好。
public Set<Integer> commonElements(Set<Integer> s1, Set<Integer> s2) {
Set<Integer> res = new HashSet<>();
for (Integer temp : s1) {
if(s2.contains(temp)) {
res.add(temp);
}
}
return res;
}
那么解决这个问题的更好方法是什么?
最佳答案
首先:为了确定两个集合的交集,您绝对必须查看两个集合中至少一个集合的所有条目(以确定它是否在另一个集合中) .没有任何魔法可以告诉您在 O(min(size(s1), size(s2)).Period.
内接下来要告诉面试官:“100 万个条目。你一定是在开玩笑。现在是 2019 年。任何像样的硬件都可以在不到一秒的时间内处理两个 100 万个条目”。 (当然:这只适用于比较便宜的对象,就像这里的 Integer 实例。如果 oneRecord.equals(anotherRecord)
是一个 super 昂贵的操作,那么 1百万条目在 2022 年可能仍然是个问题)。
然后您简要提到有各种内置方法可以解决这个问题,以及各种第 3 方库。但是您避免了其他两个答案所犯的错误:指向一个计算相交的库根本不是您作为这个问题的“解决方案”出售的东西。
你看,关于编码:Java Set 接口(interface)有一个简单解决方案:s1.retainAll(s2)
计算两个集合的连接,因为它从 s1 中删除所有元素不在 s2 中。
显然,您必须在采访中提到这将修改 s1。
如果要求不修改 s1 或 s2,您的解决方案是一种可行的方法,并且对于运行时成本没有任何办法。如果是这样,您可以为两个集合调用 size()
并迭代条目较少的集合。
或者,你可以这样做
Set<String> result = new HashSet<>(s1);
return result.retain(s2);
但最后,您必须迭代一个集合,并为每个元素确定它是否在第二个集合中。
当然,对此类问题的真正回答始终总是向面试官表明您能够将问题分解为不同的方面。您概述了基本限制,概述了不同的解决方案并讨论了它们的优缺点。以我为例,我希望你坐下来写一个这样的程序:
public class Numbers {
private final static int numberOfEntries = 20_000_000;
private final static int maxRandom = numberOfEntries;
private Set<Integer> s1;
private Set<Integer> s2;
@Before
public void setUp() throws Exception {
Random random = new Random(42);
s1 = fillWithRandomEntries(random, numberOfEntries);
s2 = fillWithRandomEntries(random, numberOfEntries);
}
private static Set<Integer> fillWithRandomEntries(Random random, int entries) {
Set<Integer> rv = new HashSet<>();
for (int i = 0; i < entries; i++) {
rv.add(random.nextInt(maxRandom));
}
return rv;
}
@Test
public void classic() {
long start = System.currentTimeMillis();
HashSet<Integer> intersection = new HashSet<>();
s1.forEach((i) -> {
if (s2.contains(i))
intersection.add(i);
});
long end = System.currentTimeMillis();
System.out.println("foreach duration: " + (end-start) + " ms");
System.out.println("intersection.size() = " + intersection.size());
}
@Test
public void retainAll() {
long start = System.currentTimeMillis();
s1.retainAll(s2);
long end = System.currentTimeMillis();
System.out.println("Retain all duration: " + (end-start) + " ms");
System.out.println("intersection.size() = " + s1.size());
}
@Test
public void streams() {
long start = System.currentTimeMillis();
Set<Integer> intersection = s1.stream().filter(i -> s2.contains(i)).collect(Collectors.toSet());
long end = System.currentTimeMillis();
System.out.println("streaming: " + (end-start) + " ms");
System.out.println("intersection.size() = " + intersection.size());
}
@Test
public void parallelStreams() {
long start = System.currentTimeMillis();
Set<Integer> intersection = s1.parallelStream().filter(i -> s2.contains(i)).collect(Collectors.toSet());
long end = System.currentTimeMillis();
System.out.println("parallel streaming: " + (end-start) + " ms");
System.out.println("intersection.size() = " + intersection.size());
}
}
这里的第一个观察结果:我决定使用 2000 万 条目来运行。我从 200 万开始,但所有三个测试的运行时间都远低于 500 毫秒。这是 2000 万美元在我的 Mac Book Pro 上打印出来的:
foreach duration: 9304 ms
intersection.size() = 7990888
streaming: 9356 ms
intersection.size() = 7990888
Retain all duration: 685 ms
intersection.size() = 7990888
parallel streaming: 6998 ms
intersection.size() = 7990888
正如预期的那样:所有交叉点都具有相同的大小(因为我为随机数生成器设置了种子以获得可比较的结果)。
令人惊讶的是:就地修改 s1 ... 是迄今为止成本最低的选择。它以 10 的因子击败流式传输。另请注意:此处的并行流式传输速度更快。当运行 100 万个条目时,顺序 流速度更快。
因此我最初提到要提及“100 万个条目不是性能问题”。这是一个非常重要的声明,因为它告诉面试官您不是那种浪费时间微优化不存在的性能问题的人。
关于java - 从 2 组中找到共同元素的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56488685/
在开发中的网页上,我在 IE 上遇到此错误 element = $(element); 此代码位于prototype.js 预期对象 如何消除此错误。 更新: 现场也使用了 jQuery。 最佳答
我有两个大小相同的嵌套数组: Array1 =[[1, 2], [], [2, 3]] Array2= [[1, 4], [8, 11], [3, 6]] 我需要将它们合并到一个数组中,如下所示: A
我有一些 jQuery 代码,当单击具有特定 ID 的项目时运行。当 ID 是 的一部分时,它就可以工作。元素,但当它位于 中时则不然元素。为什么会这样呢?我想使用 an,因为如果用户关闭了 Ja
Flex-box 规范 3声明 flex 元素不是 block 容器: A flex item establishes a new formatting context for its content
我遇到了一个意想不到的问题。 HTML JS $(function() { var $divs = $('.myDiv'); // create new div not in
我使用 Bootstrap 和 Ember.js 得到了一个无序列表。每个列表项都是一个显示新帖子的链接,每当您单击该链接时,Ember 都会添加类 active默认情况下。我正在使用 Bootstr
我正在尝试让一个函数正常工作,但运气不佳,所以我想向 Stackoverflow 智囊团提出一个新手问题! 基本上,我有一个表单,并且循环遍历所有元素以查看是否存在自定义数据属性。如果存在,则保持该元
我想映射一个可选数组,删除那些 nil 值,并使用另一个函数映射非 nil 值。 我知道我可以通过使用 compactMap 然后使用常规 map 来实现这一点,但我只想遍历数组一次。 我为此实现了一
我如何定位 li 元素,除非它们出现在 之后元素?换句话说,我想针对步骤而不是注释。 我尝试向 OL 添加一个我想从选择中排除的类,但我想出的代码不起作用。 (顺便说一句,重构 html 不是一种选
Warning 1 The element 'system.webServer' has invalid child element 'rewrite'. List of possible eleme
我正在尝试编写一个脚本,该脚本将遍历 HTML 源并创建 DOM 的 JSON 文件,然后使用 d3.js 在 TreeView 中显示该文件。我遇到的问题是不仅希望显示元素(TITLE、P、LI 等
我有以下 HTML 表单:- Option 1 Option 2
我试图在选定的 HTML 元素之后选择下一个具有类名 slider-value 的 span 元素。我尝试了多种解决方案,但没有一个有效。 我可以通过 id 选择它,但我不希望那样做使代码冗余。 $(
如果电子邮件地址无效,我想在屏幕上显示一条消息“请输入有效的电子邮件地址”。 body 元素的innerHTML 语句工作正常,但我用于p 元素的innerHTML 语句不起作用。 有一次,当我测试它
以下 jQuery 代码调用 ul 元素,查找元素内的前 三个 li 列表项,并隐藏剩余的 li 项目。然后,它附加一个 li 元素,其中显示“显示更多...”,并且在单击时显示之前隐藏的列表项。 (
我问了a question早些时候关于将编辑/删除链接与 h1 元素内联的最佳方法。我能够通过给出的答案实现这一点,但我现在有额外的要求,我需要在 h1 下方显示一个段落并编辑/删除链接。 到目前为止
我使用 MVC 4 和 knockout.js 库版本 2.1.0 显示从服务器检索到的大量文件的表中的以下摘录。 0)"> 正在正确检索数据,
我创建了一个脚本,该脚本在鼠标悬停在父容器上时激活,并且应该将其子元素移离鼠标。我目前已经让它工作了,但是代码的某些部分似乎与 REACT 代码应该是什么样子相矛盾。特别是两个部分。 我在渲染函数中使
我是 JS 新手,正在尝试理解项目 https://github.com/tastejs/todomvc 的代码 请参阅屏幕截图,我尝试对 button X 以及其父元素 div 设置断点,但在这两种
例如,假设有一个带有奇特颜色的标记: Something written here 使用 Visual Studio 2017 和 MVC 5 元素,有没有办法检查和定位当前应用了哪些样式,以及负责它
我是一名优秀的程序员,十分优秀!