C++ 这种模式有什么优雅的解决方案?多级搜索

C++ 这种模式有什么优雅的解决方案?多级搜索,c++,algorithm,search,C++,Algorithm,Search,假设我们有多个整数数组。可以将每个数组视为一个级别。我们试图找到一个元素序列,每个数组中正好有一个元素,然后使用相同的谓词进入下一个数组。例如,我们有v1、v2、v3作为数组: v1 | v2 | v3 ----------------- 1 | 4 | 16 2 | 5 | 81 3 | 16 | 100 4 | 64 | 121 我可以说谓词是:next\u element==previous\u element^2 上述示例中的有效序列是:2->4->16

假设我们有多个整数数组。可以将每个数组视为一个级别。我们试图找到一个元素序列,每个数组中正好有一个元素,然后使用相同的谓词进入下一个数组。例如,我们有
v1、v2、v3
作为数组:

v1  | v2  | v3
-----------------
1   | 4   | 16
2   | 5   | 81
3   | 16  | 100
4   | 64  | 121
我可以说谓词是:
next\u element==previous\u element^2

上述示例中的有效序列是:
2->4->16

实际上,在这个例子中没有另一个有效的序列。 我可以编写三个循环来强制执行上面提到的示例,但是如果数组的数量是可变的,但是当然知道顺序,那么如何解决这个问题呢

提示,或参考设计模式是非常感谢的。我将用C++来做,但我只是需要这个想法。
谢谢,

如果您事先订购阵列,搜索速度会更快。您可以从较小的数组开始,然后二进制搜索每个数组上的预期数字。这将是O(nklogM),n是最小数组的大小,k是数组的数量,M是较大数组的大小

如果使用Hashmaps而不是数组,则可以更快地完成此操作。这将允许您在O(n*k)中搜索

若使用反向函数(在早期数组中搜索)不是一个选项,那个么您应该从第一个数组开始,n=第一个数组的大小

为了简单起见,我将从第一个数组开始

//note the 1-based arrays
for (i : 1 until allArrays[1].size()) {
  baseNumber = allArrays[1][i];
  for (j: 2 until allArrays.size()) {
    expectedNumber = function(baseNumber);
    if (!find(expectedNumber, allArrays[j]))
        break;
    baseNumber = expectedNumber;
  }
}

您可能可以执行一些空检查并在其中添加一些布尔值,以了解序列是否存在

您可以生成一个单独的索引,将索引从一个数组映射到另一个数组的索引。从索引中可以快速查看解决方案是否存在


生成索引将需要一种蛮力方法,但您只需执行一次。如果你想改进数组搜索,考虑使用更合适的数据结构来允许快速搜索(例如红黑树而不是数组)。

< P>我将保持所有向量,这样当搜索元素时,我可以有<代码> O(log n)< /Cord>复杂度。因此,对于总共
k
向量,您将得到类似
O(k*logn)

的复杂性(设计模式应用于类和API设计以提高代码质量,但它们不用于解决计算问题)

视情况而定:

  • 如果阵列是随机排列的,并且您需要有限的空间,那么暴力是唯一的解决方案。O(Nk)时间(k=3),O(1)空间
  • 如果谓词不可逆(例如
    SHA1(next_elem)或xor SHA1(prev_elem)==0x1234
    ),则暴力也是唯一的解决方案
  • 如果可以节省空间,那么就为v2和v3创建哈希集,这样就可以快速找到满足谓词的下一个元素。O(N+bk)时间,O(kN)空间。(b=满足给定上一个元素的谓词的下一个元素的最大数量)
  • 如果数组已排序并有界,还可以使用二进制搜索而不是哈希表,以避免使用空格。O(N(logn)k-1+bk)时间,O(1)空间
  • (由于递归,所有空间计数不考虑堆栈使用。)

    消耗O(Nbk)空间的一般方法是通过连续过滤构建解决方案,例如:

    solutions = [[1], [2], ... [N]]
    
    filterSolution (Predicate, curSols, nextElems) {
       nextSols = []
       for each curSol in curSols:
          find elem in nextElems that satisfy the Predicate
          append elem into a copy of curSol, then push into nextSols
       return nextSols
    }
    
    for each levels:
      solutions = filterSolution(Predicate, solutions, all elems in this level)
    return solutions
    

    如果谓词保留数组中的顺序(例如,在您的示例中,如果值都保证为非负),则可以调整合并算法。考虑每个数组的关键是结束值(在应用所有谓词所需的谓词后得到的值)。

    如果谓词没有保留顺序(或者数组没有按开始顺序排列),您可以先按结束值排序,但这样做的需要表明另一种方法可能更好(如其他地方建议的哈希表)

    基本上,检查所有数组的下一个结束值是否相等。如果没有,请跨过最低点(仅在一个阵列中)并重复。如果这三个都相等,这是一个(可能的)解决方案-在搜索下一个之前,先对所有三个进行检查

    “可能”解决方案,因为您可能需要执行检查-如果谓词函数可以将多个输入值映射到同一个输出值,则可能会出现某些数组中的值(但不是第一个或最后一个)错误的情况


    编辑-当谓词没有将每个输入映射到唯一的输出时,可能会出现更大的问题-此时无法思考。基本上,合并方法可以很好地工作,但只适用于某些类型的谓词函数。

    之前的海报建议使用二进制搜索的排序数组-这将比红黑树快得多。如果需要将许多项插入数组的中间,我会考虑列表而不是数组。这实际上是内存使用和速度之间的折衷。我刚才在问题中给出了一个谓词的例子。对于我正在使用的谓词,元素实际上没有排序,我认为它们不能为该谓词排序。我想说的是,如果数组的数量是可变的,那么就可以找到元素序列。@AraK我的答案现在有帮助吗?非常感谢,我想这就是我要找的:)你需要的是算法,而不是模式。这将是一个问题的解决方案。这里有一个问题:谓词可能是任意复杂的,因此可以同时处理1到N个数组。。。很难想出一个解决方案可以解决整个问题。此外,是否存在重复的可能性,如果存在,您如何处理它们(您希望每个重复使用一个解决方案,或者希望每个批次只使用一个解决方案?)我喜欢这种流水线的想法!