【问题标题】:Efficient way of finding sequential numbers across multiple arrays?跨多个数组查找序列号的有效方法?
【发布时间】:2017-04-21 15:10:39
【问题描述】:

我不是在寻找任何代码或为我做任何事情。我需要一些帮助才能朝着正确的方向开始,但不知道如何去做。如果有人可以提供一些有关如何解决这些问题的资源,我将不胜感激。我坐在我的笔记本上,在设计一种可以做我想做的事情的算法时遇到了麻烦。

我大概可以做到:

foreach element in array1
    foreach element in array2
        check if array1[i] == array2[j]+x

我相信这对正向和反向序列都适用,对于倍数只需检查array1[i] % array2[j] == 0。我有一个包含 int 数组的列表,并且得到了list[index](对于array1)和list[index+1] 对于array2,但是这个解决方案可能会变得复杂而冗长,特别是对于大型数组和这些数组的大型列表.因此,我正在寻找更好的解决方案。


我正在尝试提出一种算法来查找不同数组中的序列号。

例如:

[1, 5, 7][9, 2, 11] 会发现 12 是连续的。

这也适用于多个数组中的多个序列。因此,如果有第三个数组[24, 3, 15],它还将在该序列中包含3,并继续下一个数组,直到没有与last sequential element + 1匹配的数字。

它还应该能够在数组之间找到多个序列。

例如:

[1, 5, 7][6, 3, 8] 会发现 56 是连续的,78 也是连续的。


我也有兴趣寻找反向序列。

例如: [1, 5, 7][9, 4, 11] 将返回 54 是反向顺序的。


全部示例:

[1, 5, 8, 11][2, 6, 7, 10] 将返回 12 是顺序的,56 是顺序的,87 是反向顺序的,11 和 @987654@53是反向顺序的。

也可以重叠:

[1, 5, 7, 9][2, 6, 11, 13] 将返回 12 顺序,56 顺序以及 76 反向顺序。

我还想扩展它以检查差异为x 的数字(以上示例检查差异为1)。



除了所有这些(尽管这可能是一个不同的问题),我还想检查倍数,

示例: [5, 7, 9][10, 27, 8] 将返回 510 作为倍数,927 作为倍数。

和数字相同的地方。

示例: [3, 5, 7][13, 23, 25] 将返回 31323 具有相同的个位。

【问题讨论】:

  • 先对数组进行排序,这样更容易找到序号

标签: arrays algorithm computer-science


【解决方案1】:

使用字典(set 或 hashmap)

dictionary1 = {}

遍历第一个数组中的每个项目并将其添加到字典中。 [1, 5, 7]

现在dictionary1 = {1:true, 5:true, 7:true}

dictionary2 = {}

现在检查[6, 3, 8] 中的每个项目并查找它是否是序列的一部分。

6 是序列的一部分,因为 dictionary1[6+1] == true 所以dictionary2[6] = true

我们得到dictionary2 = {6:true, 8:true}

现在设置dictionary1 = dictionary2dictionary2 = {},然后转到第三个数组.. 以此类推。

我们只跟踪序列。 由于每次查找是 O(1),并且我们对每个数字进行 2 次查找(例如 6-1 和 6+1),因此总数为 n*O(1),即 O(N)(N 是数字的数量跨所有数组)。

【讨论】:

  • 感谢您的回答。我最终使用它作为我的解决方案,除了 enum 值表示增加/减少/等。最终对这个解决方案感到满意。谢谢。
【解决方案2】:

您的伪代码中概述的蛮力方法将是 O(c^n)(指数),其中 c 是每个数组的平均元素数,n 是总数组的数量。

如果输入空间是稀疏(意味着平均而言,缺失的数字比显示的数字要多),那么加速这个过程的一种方法是首先创建一个单一的排序集来自所有不同数组的唯一编号。然后,此“主”集将允许您在任何不可行的序列上提前退出(即循环中的 break 语句)。

例如,如果我们有输入数组[1, 5, 7][6, 3, 8][9, 11, 2],主有序集将是{1, 2, 3, 5, 6, 7, 8, 9, 11}。如果我们正在寻找n+1 类型的序列,我们可以跳过continuing检查任何包含3911 的序列(因为n+1 值不存在在排序集中的下一个索引处。虽然在这个特定示例中加速并不剧烈,但如果您有数百个输入数组和非常大范围的 n(稀疏)值,那么加速应该是指数的,因为您将能够在许多排列上提前退出。如果输入空间不是稀疏的(例如在这个例子中我们没有很多洞),加速将小于指数。

进一步的改进是存储一组“主”键值对,其中键是n 值,如上例所示,该对的值部分是索引列表包含该值的任何数组。上一个示例的主集将是:{[1, 0], [2, 2], [3, 1], [5, 0], [6, 1], [7, 0], [8, 1], [9, 2], [11, 2]}。使用这种架构,扫描时间可能会低至O(c*n),因为您可以只遍历这个单个排序的主集以查找有效序列,而不是遍历所有子数组。通过还要求数组索引递增,您可以清楚地看到1->2 序列可以跳过,因为数组的顺序不正确,2->3 序列等也是如此。注意这个玩具示例有点过于简化,因为在实践中,您需要键值对的值部分的索引列表。如果 n 的相同值曾经出现在多个数组中(重复值),这将是必要的。

【讨论】:

  • 感谢您抽出宝贵时间回答。虽然这很聪明,但不幸的是,仅仅因为我的号码是如何设置的,它在我的情况下不起作用。不过我确实学到了一些东西,并且将来可能会使用这种逻辑。
猜你喜欢
  • 2014-01-11
  • 1970-01-01
  • 2011-10-08
  • 1970-01-01
  • 1970-01-01
  • 2019-06-12
  • 2019-05-31
  • 2014-07-10
  • 1970-01-01
相关资源
最近更新 更多