昨天我把干净的洗衣店的袜子配对,弄清楚我做的方式效率不高。我正在做一个天真的搜索 - 挑选一个袜子并 “迭代” 堆,以找到它的对。这需要迭代在 n / 2 * N / 4 = N 2/8上平均的袜子。
作为一名计算机科学家,我在想我能做些什么?当然,为了实现 O(NlogN)解决方案,我们会想到排序(根据大小 / 颜色 / ...)。
哈希或其他非就地解决方案不是一种选择,因为我无法复制我的袜子(尽管如果可能的话可能会很好)。
所以,问题基本上是:
鉴于一堆n
双袜子,包含2n
元素(假设每个袜子只有一对匹配),有效配对多达对数额外空间的最佳方法是什么? (我相信如果需要,我会记住那些信息。)
我将感谢一个解决以下方面的答案:
已经提出了排序解决方案,但排序有点过多 :我们不需要订单; 我们只需要平等团体 。
因此散列就足够了(而且速度更快)。
当需要在大型数据集上散列连接或散列聚合时,这种递归散列分区实际上是由SQL Server完成的。它将构建输入流分配到许多独立的分区中。该方案线性地扩展到任意数量的数据和多个 CPU。
如果您可以找到提供足够桶的分发键(散列键),并且每个桶足够小以便快速处理,则不需要递归分区。不幸的是,我不认为袜子有这样的属性。
如果每个袜子都有一个名为 “PairID” 的整数,可以根据PairID % 10
(最后一位数)轻松地将它们分配到 10 个桶中。
我能想到的最好的真实世界分区是创建一个桩的矩形 :一个是颜色,另一个是图案。为什么是矩形?因为我们需要 O(1)随机访问桩。 (3D 长方体也可以使用,但这不太实用。)
更新:
并行性怎么样?多个人可以更快地匹配袜子吗?
元素清晰度问题怎么样?正如文章所述,元素清晰度问题可以用O(N)
来解决。对于袜子问题也是如此O(N)
如果你只需要一个分配步骤(我提出了多个步骤只是因为人类计算不好),如果你在md5(color, length, pattern, ...)
分配一步md5(color, length, pattern, ...)
,即所有属性的完美哈希 ))。
显然,人们不能比O(N)
更快,所以我们已达到最佳下限 。
虽然输出不完全相同(在一种情况下,只是一个布尔值。在另一种情况下,袜子对),渐近复杂性是相同的。
由于人脑的结构与现代 CPU 完全不同,这个问题没有任何实际意义。
人类可以通过 “查找匹配对” 可以成为一个不太大的集合的一个操作来赢得 CPU 算法。
我的算法:
spread_all_socks_on_flat_surface();
while (socks_left_on_a_surface()) {
// Thanks to human visual SIMD, this is one, quick operation.
pair = notice_any_matching_pair();
remove_socks_pair_from_surface(pair);
}
至少这是我在现实生活中使用的,我发现它非常有效。缺点是它需要一个平坦的表面,但它通常很丰富。
案例 1 :所有袜子都是相同的(这就是我在现实生活中所做的事情)。
选择其中任意两个来做一对。恒定时间。
案例 2 :有一定数量的组合(所有权,颜色,大小,纹理等)。
使用基数排序 。这只是线性时间,因为不需要比较。
案例 3 :预先不知道组合的数量(一般情况)。
我们必须进行比较以检查两只袜子是否成对。选择一种基于O(n log n)
比较的排序算法。
然而在现实生活中,当袜子的数量相对较小(恒定)时,这些理论上最优的算法将不能很好地工作。它可能比顺序搜索花费更多的时间,这在理论上需要二次时间。
已经提出了排序解决方案,但排序有点过多 :我们不需要订单; 我们只需要平等团体 。
因此散列就足够了(而且速度更快)。
当需要在大型数据集上散列连接或散列聚合时,这种递归散列分区实际上是由SQL Server完成的。它将构建输入流分配到许多独立的分区中。该方案线性地扩展到任意数量的数据和多个 CPU。
如果您可以找到提供足够桶的分发键(散列键),并且每个桶足够小以便快速处理,则不需要递归分区。不幸的是,我不认为袜子有这样的属性。
如果每个袜子都有一个名为 “PairID” 的整数,可以根据PairID % 10
(最后一位数)轻松地将它们分配到 10 个桶中。
我能想到的最好的真实世界分区是创建一个桩的矩形 :一个是颜色,另一个是图案。为什么是矩形?因为我们需要 O(1)随机访问桩。 (3D 长方体也可以使用,但这不太实用。)
更新:
并行性怎么样?多个人可以更快地匹配袜子吗?
元素清晰度问题怎么样?正如文章所述,元素清晰度问题可以用O(N)
来解决。对于袜子问题也是如此O(N)
如果你只需要一个分配步骤(我提出了多个步骤只是因为人类计算不好),如果你在md5(color, length, pattern, ...)
分配一步md5(color, length, pattern, ...)
,即所有属性的完美哈希 ))。
显然,人们不能比O(N)
更快,所以我们已达到最佳下限 。
虽然输出不完全相同(在一种情况下,只是一个布尔值。在另一种情况下,袜子对),渐近复杂性是相同的。
由于人脑的结构与现代 CPU 完全不同,这个问题没有任何实际意义。
人类可以通过 “查找匹配对” 可以成为一个不太大的集合的一个操作来赢得 CPU 算法。
我的算法:
spread_all_socks_on_flat_surface();
while (socks_left_on_a_surface()) {
// Thanks to human visual SIMD, this is one, quick operation.
pair = notice_any_matching_pair();
remove_socks_pair_from_surface(pair);
}
至少这是我在现实生活中使用的,我发现它非常有效。缺点是它需要一个平坦的表面,但它通常很丰富。
案例 1 :所有袜子都是相同的(这就是我在现实生活中所做的事情)。
选择其中任意两个来做一对。恒定时间。
案例 2 :有一定数量的组合(所有权,颜色,大小,纹理等)。
使用基数排序 。这只是线性时间,因为不需要比较。
案例 3 :预先不知道组合的数量(一般情况)。
我们必须进行比较以检查两只袜子是否成对。选择一种基于O(n log n)
比较的排序算法。
然而在现实生活中,当袜子的数量相对较小(恒定)时,这些理论上最优的算法将不能很好地工作。它可能比顺序搜索花费更多的时间,这在理论上需要二次时间。