打印所有因素组合的算法

198 阅读5分钟

在这篇文章中,我们将讨论打印一个给定数字的每一个因子组合的算法(所有因子化),我们已经探讨了递归和部分迭代的方法。

我们会看到什么?

问题陈述

我们必须设计并实现一种算法,打印出给定数字的所有唯一的因子组合。例如,假设给定的数字是16,那么输出结果应该是这样的

2 2 2 2 2 2
4
2

8
4

4

有许多方法可以解决打印一个数字的因子组合的问题。下面讨论其中的一些方法:

使用回溯概念的迭代方法

解决这个问题的基本思路是将迭代的数字乘以一个乘积变量,这个乘积变量最初为1,并在每一步检查乘积是否小于、等于或超过这个数字。

如果乘积小于输入的数字,我们就用下一个数字乘以乘积,然后再检查。

如果乘积等于数字,我们将输出乘积的因子组合(正在迭代的数字,乘积使其等于输入的数字),然后从乘积中删除或除以最后一个乘积的数字(即我们正在使用回溯的概念),并通过将下一个数字乘积来测试。

如果积超过了这个数字,我们就重复同样的回溯过程,直到积等于或小于输入的数字。

我们需要知道哪些因子的组合形成了乘积,为此,我们必须将每个被乘的数字存入列表或堆栈中。当我们从乘积中删除任何数字时,我们也必须从列表或堆栈中弹出或删除它。

在Python中的实现

factors = []
num = int(input("Enter a number: "))

def factorCombinations(n, product):
    global l
    
    # The base condition for recursive call
    if product == num:
        print(factors)
        return
        
    for i in range(n, int(num/2)+1):
        # Returning to the last recursive call, if product exceeds the num.
        if product*i > num:
            return 
            
        # Multiplying the number to the product
        product *= i
        factors.append(i)
        
        # Recursively calling the function with same number
        factorCombinations(i, product)
        
        # Using the backtracking approach
        factors.pop()
        product //= i
        
factorCombinations(2, 1)

在findCombinations(n, product)中,函数声明n是下一个要乘以乘积变量的数字,即第二个参数。

在每个递归调用或步骤中,产品值被更新并与输入的数字num进行比较。

如果乘积变量等于num变量,我们就打印列表中的因子组合,并返回或回溯到最后一次递归调用,从乘积中删除最后一个被乘的因子,并用下一个迭代的i值测试。

我们对相同的i值重复递归调用,即findCombinations(i, product),因为组合可能包括重复的因子,例如,16=[2, 2, 2, 2]。

递归方法

递归方法从3个参数开始:数字,在这个方法中作为乘积,类似于迭代方法,在每个递归步骤中存储当前的乘积,存储因子组合的字符串(printFactors),以及作为原始数字输入的父值(parentVal)。

在递归块内部,我们定义了一个新的变量newVal,最初给出的是parentVal(父值)的值。在number-1到2的范围内进行迭代,每次迭代时递减器i会减少1。

然后我们检查这个数字是否能被i整除,如果能被整除,则检查三个条件。条件一是如果newVal大于i的值,我们将newVal的值改为i。条件二是如果数字除以i(number/i)小于或等于parentVal,并且i小于或等于parentVal,数字除以i(number/i)小于或等于i,则打印parentFactors字符串,将其与变量i、装饰用空格和数字除以i的整数值连接起来。检查第三个条件,即如果i小于parentVal,我们通过调用printFactors函数来执行递归调用,参数为数字/i的整数值、parentFactors的连接字符串、i和一个空格字符,以及newVal作为第三个参数。

这种递归方法需要3个输入,即一个字符串,用于在while循环中携带i的当前值,以进行后续的还原,还有一个临时的整数,以知道何时不打印重复的反转,即8*3和3*8。

在Python中的实现

def printFactors(number, parentFactors, parentVal):
    ''' Initialising the variable newVal with value parentVal '''
    newVal = parentVal
    
    ''' Initialising the iterable variable i iterating through number-1 to 2 '''
    i = number-1
    while (i>=2):
    
        ''' Checking if the number is divisible by i '''
        if (number % i == 0):
            
            ''' Case when newVal is greater than i '''
            if (newVal > i) :
                
                ''' Replacing the current value of newVal with i '''
                newVal = i
            
            ''' Case when number/i is less than or equal to
            parentVal, i is less than or equal to parentVal 
            and number/i is less than or equal to i '''
            if (number / i <= parentVal and i <= parentVal and number / i <= i):
                
                ''' Printing the string of the desired output, 
                which is a combination of the factors 
                giving product equal to the parentVal '''
                print(str(parentFactors)+str(i)+" "+str(int(number/i)))
                
                ''' Setting the newVal variable, the integer value of number/i '''
                newVal = int(number/i)
            
            ''' Case when i is less than or equal to parentVal '''
            if (i <= parentVal):
                
                ''' Recursively calling the printFactors to 
                print the next combination of factors '''
                printFactors(int(number/i), str(parentFactors) + str(i) + " ", newVal)

        ''' Decrementing the i variable '''
        i-=1

printFactors(16,"",16)

结论

在OpenGenus的这篇文章中,我们讨论了如何解决打印给定数字的因子的所有唯一组合的问题。我们讨论了使用回溯概念递归迭代的方法。