【问题标题】:Making combinations recursively递归地进行组合
【发布时间】:2018-06-08 08:26:05
【问题描述】:

我有一个类似这样的层结构:

   1.1   
   1.2  
   2.1  
   3.1  
   3.2  
   4.1  
   5.1  

我想为每个项目输出所有可能的组合,但不包括顺序比自己高的项目,顺序是第一个数字,例如:

5.1会有以下组合:

(4.1, 3.1, 2.1, 1.1)  
(4.1, 3.1, 2.1, 1.2)  
(4.1, 3.2, 2.1, 1.1)   
(4.1, 3.2, 2.1, 1.2) 

4.1 将拥有:

(3.1, 2.1, 1.1)  
(3.1, 2.1, 1.2)  
(3.2, 2.1, 1.1)   
(3.2, 2.1, 1.2)  

我想用递归函数来做,我尝试了一些东西,但它不能正常工作,这里是伪代码。
我从图层顺序开始,一直向下直到它到达顺序为 1 的图层。

function recursion (layer)
    if layer.order > 1 do 
       for iterationLayer in allLayers do
          if iterationLayer.order == (layer.order - 1) do
              print iterationLayer.name
              recursion iterationLayer
    else
      end of combination

对于 4.1 案例

,这段代码给了我类似的东西
(3.1, 2.1, 1.1) 
(1.2)
(3.2, 2.1, 1.1) 
(1.2) 

之所以这样,是因为当递归到达最后一个 for 循环时,它会从底部回溯到顶部,有人对此有解决方案吗?

【问题讨论】:

  • 这类问题不用递归更容易解决,是不是一定要用递归来解决?

标签: recursion matrix combinations layer


【解决方案1】:

伪代码:

    function recursionMain(level)
        for iterationLayer in allLayers where (layer.level == level)
            recursion (iterationLayer, new list)


    function recursion(currentLayer, currentLayerList)

        remainingLevelsList = get the distinct list of levels left to visit

        if remainingLevelsList not empty
           lowestRemamingLevel = get the lowest number from remainigLevelsList
           for iterationLayer in allLayers where (layer.level == lowestRemainingLevel)
              recursion (iterationLayer, currentLayerList + currentLayer)
        else
          print the list(combination) / end of combination

这是 C# 中的工作示例:

static void GetCombinationsR(int level)
{
    foreach (Layer layer in layers.Where(l => l.Level == level))
    {
        GetCombinationsR(layer, new List<Layer>());
    }
}

static void GetCombinationsR(Layer layer, List<Layer> currentLayers)
{
    // Declaring new list so we don't loose the list of previous layers in currentLayers
    List<Layer> currentLayers2 = new List<Layer>();
    currentLayers2 = currentLayers2.Union(currentLayers).ToList();
    currentLayers2.Add(layer);

    // Getting the list of remaining levels because we are not certain
    // if level 1 is the lowest or if some levels are skipped
    List<int> remainingLevels = layers.Select(l => l.Level).Where(l => l < layer.Level).ToList();
    if (remainingLevels.Count() > 0)
    {
        int firstLowerLevel = remainingLevels.OrderByDescending(l => l).First();

        foreach (Layer layerByValue in layers.Where(l => l.Level == firstLowerLevel).ToArray())
        {
            GetCombinationsR(layerByValue, currentLayers2);
        }
    }
    else
    {
        PrintResultList(currentLayers2);
    }
}


    static void PrintResultList(List<Layer> resultList)
    {
        StringBuilder sb = new StringBuilder();
        foreach (Layer layer in resultList)
        {
            sb.Append(layer.Level).Append(": ").Append(layer.Value).Append(" -> ");
        }
        sb = sb.Remove(sb.Length - 4, 4);
        Console.WriteLine(sb.ToString());
    }

【讨论】:

    【解决方案2】:

    也许你需要这样的东西:

    function recursion (layer, combination)
        if layer = 0
              print combination
        else
           for (i = 0; i < layer.itemcount; i++)   
              recursion(layer - 1, combination + layer.item[i])
    
    recursion(layer-1, empty[])
    

    Delphi 示例(不是最优的,我们可以更快地搜索并提前中断循环)

    var
      A: TArray<string>;
    
      procedure recursion (layer: Integer; combination: string);
      var
        i: integer;
      begin
        if layer = 0 then
           Memo1.Lines.Add(combination)
        else
           for i := 0 to High(A) do
              if A[i][1] = IntToStr(layer) then //primitive check of layer
                  recursion(layer - 1, combination + A[i] + ', ')
      end;
    
    
    begin
      A := ['1.1','1.2','2.1','3.1','3.2','4.1','5.1'];
      recursion(4, '');
    
    generates
    
    4.1, 3.1, 2.1, 1.1, 
    4.1, 3.1, 2.1, 1.2, 
    4.1, 3.2, 2.1, 1.1, 
    4.1, 3.2, 2.1, 1.2, 
    

    【讨论】:

    • 试过了,它不起作用,它在一个组合中显示两次具有相同顺序的项目。我有其他解决方案,但如果可能的话,我想让它与递归一起工作。
    • 查看工作示例(我的伪代码假设您的项目被分隔为级别,新代码不依赖于此)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多