将迭代算法转换为递归算法的问题

时间:2015-11-16 20:00:51

标签: algorithm vba recursion

我很久没有考虑过递归,所以请耐心等待我。

我基本上需要编写一个子程序,如果它们总计给定的数字,它将输出所有数字序列。迭代方法将在以下部分中显示

Sub IterFunc()
    For i = 1 To 5
        For j = 1 To 5
            For k = 1 To 5
                If i + j + k = 4 Then
                    Debug.Print i & ", " & j & ", " & k
                End If
            Next k
        Next j
    Next i
End Sub

如果序列由3个整数组成,则可以正常工作,但它不适用于序列中任意数量的整数。因此需要一种递归方法。以下是我尝试重写子例程的递归版本

Sub RecuFunc(ByRef tot As Long)
    For i = 1 To 5
        tot = tot + i
        If tot = 5 Then
            Debug.Print i
        ElseIf tot < 5 Then
            Call RecuFunc(tot)
        ElseIf tot > 5 Then
            Call RecuFunc(tot - i)
        End If
    Next i
End Sub

Sub test2()
    Call RecuFunc(0)
End Sub

很快就出现了几个问题:a)我不太确定如何在总匹配时存储序列来输出它b)似乎我需要以某种方式&#34;重置&#34;变量tot,但我的方法似乎不起作用。

任何想法都会很棒。如果我的问题很原始,我会道歉。

谢谢!

3 个答案:

答案 0 :(得分:1)

这是一个递归函数,给定一个整数n和一个目标值target(假设为> 0),返回一个表格的所有字符串的集合,例如: "1 + 2 + 1 + 1",其中总和中的数字在1,...,n范围内,并且它们与目标相加。集合是一种自然的数据结构,使用字符串的优势在于它可以很容易地将新条款用于总和:

Function IntSums(n As Long, target As Long) As Collection
    Dim sums As New Collection
    Dim partialSums As Collection
    Dim i As Long, m As Long, sum As Variant

    If target = 1 Then
        sums.Add target
        Set IntSums = sums
        Exit Function
    End If
    m = IIf(n < target, n, target) 'm is min(n,target)
    For i = 1 To m
        If i = target Then
            sums.Add Trim(Str(target))
        Else
            Set partialSums = IntSums(n, target - i)
            For Each sum In partialSums
                sums.Add i & " + " & sum
            Next sum
        End If
    Next i
    Set IntSums = sums
End Function

测试功能:

Sub test()
    Dim s As Variant, sum As Variant
    Set s = IntSums(5, 5)
    For Each sum In s
        Debug.Print sum
    Next sum
End Sub

输出:

1 + 1 + 1 + 1 + 1
1 + 1 + 1 + 2
1 + 1 + 2 + 1
1 + 1 + 3
1 + 2 + 1 + 1
1 + 2 + 2
1 + 3 + 1
1 + 4
2 + 1 + 1 + 1
2 + 1 + 2
2 + 2 + 1
2 + 3
3 + 1 + 1
3 + 2
4 + 1
5

答案 1 :(得分:1)

我认为您要做的是列出具有有限数量部件的数字的分区。这是JavaScript中的一种递归,这种语法的语法与C:

的距离不太远
function ps(n,k,max,r){
  if (n == 0){
    console.log(r.substr(1));
    return;
  }

  for (var i=Math.min(max,n-k+1); i*k>=n; i--){
    ps(n - i,k - 1,i,r + "," + i);
  }
}

ps(8,3,8,"")

/*
6,1,1
5,2,1
4,3,1
4,2,2
3,3,2
*/

对于不受限制的版本,我们会移除k

function ps(n,max,r){
  if (n == 0){
    console.log(r.substr(1));
  }

  for (var i=Math.min(max,n); i>0; i--){
    ps(n - i,i,r + "," + i);
  }
}

ps(8,8,"")

答案 2 :(得分:0)

这里也许不是一个完整的答案 - 我不了解VB - 但是要让你开始朝着正确的方向前进。几个观察结果:首先,通常是迭代的&gt;递归。其次,你正在做蛮力,可能找到一种更有效的方法。考虑将10的总值分成三个整数的总和: 10 = 3 + 5 + 2 =(1 + 1 + 1)+(1 + 1 + 1 + 1 + 1)+(1 + 1) 10 = 4 + 5 + 1 =(1 + 1 + 1 + 1)+(1 + 1 + 1 + 1 + 1)+(1) 如您所见,基本上您正在转动括号所在的位置。就递归而言,可以通过减去&#34; i&#34;来实现10到3的总和。从10开始,然后递归地将(10-i)分成两个总和。