找到给定的未排序整数列表中不存在(且大于列表的最小值)的第一个(最小)整数的最快方法是什么?
我原始的方法是对它们进行排序并逐步浏览列表,是否有更好的方法?
If you have a question about… •algorithm and data structure concepts
它是关于恕我直言的话题。
找到给定的未排序整数列表中不存在(且大于列表的最小值)的第一个(最小)整数的最快方法是什么?
我原始的方法是对它们进行排序并逐步浏览列表,是否有更好的方法?
If you have a question about… •algorithm and data structure concepts
它是关于恕我直言的话题。
Answers:
假设您说“数字”的意思是“整数”,则可以使用大小为2 ^ n的位向量,其中n是元素数(例如,您的范围包括1到256之间的整数,则可以使用256-位或32字节的位向量)。当您在范围的位置n遇到整数时,请设置第n位。
枚举整数集合后,您可以遍历位向量中的位,寻找设置为0的任何位的位置。它们现在与丢失的整数的位置n相匹配。
这是O(2 * N),因此是O(N),并且可能比对整个列表进行排序更节省内存。
仅出于神秘和“聪明”,在只有一个“孔”的数组的特殊情况下,您可以尝试基于XOR的解决方案:
类似于位向量解决方案,此过程将在大约2N的时间内运行,但对于任何N> sizeof(int),都需要较少的存储空间。但是,如果数组具有多个“孔”,则X将是所有孔的XOR“和”,这将很难或不可能分离为实际的孔值。在那种情况下,您会退回到其他方法,例如其他答案中的“枢轴”或“位向量”方法。
您也可以使用类似于数据透视方法的方法来递归此操作,以进一步降低复杂性。根据枢轴点重新排列阵列(这将是左侧的最大值和右侧的最小值;在枢轴旋转时找到整个数组的最大值和最小值将是微不足道的)。如果枢轴的左侧有一个或多个孔,则仅递归到该侧;否则递归到另一侧。在任何可以确定只有一个孔的点上,都可以使用XOR方法找到它(总的来说,这比继续向下一直旋转到具有已知孔的两个元素的集合要便宜得多,这是该方法的基本情况纯数据透视算法)。
不,不是。由于任何尚未扫描的数字始终可以是填充给定“漏洞”的数字,因此您无法避免至少扫描一次每个数字,然后将其与可能的邻居进行比较。您可能可以通过建立一棵左右的二叉树然后从左向右遍历直到找到一个孔来加快处理速度,但这实际上与排序的复杂度相同,因为它是排序的。而且您可能不会想出比Timsort更快的方法。
不使用额外存储空间或假设整数宽度(32位)的解决方案。
在一次线性扫描中,找到最小的数字。让我们称之为“分钟”。O(n)时间复杂度。
选择一个随机的枢轴元素并进行快速排序样式分区。
如果枢轴最终到达位置=(“ pivot”-“ min”),则在分区的右侧递归,否则在分区的左侧递归。这里的想法是,如果从头开始没有孔,则枢轴将位于第(“ pivot”-“ min”)位置,因此第一个孔应位于分隔壁的右侧,反之亦然。
基本案例是由1个元素组成的数组,并且孔位于该元素和下一个元素之间。
预期的总运行时间复杂度为O(n)(带常数的8 * n),最坏的情况为O(n ^ 2)。在这里可以找到类似问题的时间复杂度分析。
我相信,如果可以保证没有重复*,那么我想出了一些应该可以普遍有效地工作的东西(但是,它应该可以扩展到任意数量的孔和整数范围)。
该方法背后的想法就像快速排序,因为我们找到了一个枢轴并对其进行了分区,然后在有孔的一侧递归。要查看哪一侧有孔,我们找到最低和最高的数字,然后将其与该侧的支点和数值个数进行比较。假设枢轴为17,最小数量为11。如果没有孔,则应该有6个数字(11、12、13、14、15、16、17)。如果有5,我们知道在那一侧有一个洞,我们可以在那一侧递归找到它。我很难对此进行更清楚的解释,所以让我们举个例子。
15 21 10 13 18 16 22 23 24 20 17 11 25 12 14
枢:
10 13 11 12 14 |15| 21 18 16 22 23 24 20 17 25
15是枢轴,用管道(||
)表示。枢轴的左侧有5个数字,应为(15-10),右侧为9,应有10(25-15)。因此,我们在右侧进行递归;我们会注意到,如果孔与之相邻,则前一个边界为15(16)。
[15] 18 16 17 20 |21| 22 23 24 25
现在左侧有4个数字,但应该有5个(21-16)。因此,我们在那里递归,并再次注意上一个边界(在方括号中)。
[15] 16 17 |18| 20 [21]
左侧有正确的2个数字(18-16),但右侧有1个而不是2(20-18)。根据我们的结束条件,我们可以将1的数字与两边的数字(18,20)进行比较,看看是否缺少19或再次递归一次:
[18] |20| [21]
左侧的大小为零,在枢轴(20)和先前的边界(18)之间有间隙,因此19是孔。
*:如果存在重复项,则可以使用哈希集在O(N)的时间内将其删除,同时将整个方法保留为O(N),但这可能比使用其他方法花费更多的时间。