【问题标题】:Why this two backtracking algorithm have same outputs?为什么这两个回溯算法具有相同的输出?
【发布时间】:2020-05-23 11:59:45
【问题描述】:

我已经实现了两个回溯算法来解决 Codewars (https://www.codewars.com/kata/5a6b24d4e626c59d5b000066) 上的挑战。我的问题是我明白为什么第一个实现有效,但不明白为什么第二个实现。我认为我的问题出在最后一行带有井号的 return 语句中。我不明白为什么当回溯终止时,因为找到了解决方案,第二个实现返回正确的解决方案而不是空列表。是不是因为当解决方案被传递给函数的前一个调用时,他在前一个调用中的值(即元素少)被完整的解决方案覆盖?

第一:

def square_sums_row(n):
    a , sol = [ x for x in range(1,n+1)] , []
    def recurse(a,sol):
        if a == [] : 
            return sol 
        for i,x in enumerate(a) :
            if is_valid(x,sol) :
                sol.append(x)
                iterate = recurse(a[:i]+a[i+1:],sol) ###########
                if iterate : ###########
                    return iterate #########
                sol.pop(-1)
        return False
    def is_valid(x,sol):
        if len(sol) == 0 :
            return True
        if (( sol[-1] + x )**0.5) % 1 == 0:
            return True
        return False
    return recurse(a,sol)

第二:

def square_sums_row(n):
    s , sol = [ x for x in range(1,n+1)] , []
    def recurse(s,sol):
        if s == [] :  
            return sol
        for i,x in enumerate(s) :
            if is_valid(x,sol) :
                sol.append(x)
                if recurse(s[:i]+s[i+1:],sol) : ###########
                    return sol ##############
                sol.pop(-1)
        return False
    def is_valid(x,sol):
        if len(sol) == 0 :
            return True
        if (( sol[-1] + x )**0.5) % 1 == 0:
            return True
        return False
    return recurse(s,sol)

【问题讨论】:

    标签: python python-3.x algorithm recursion backtracking


    【解决方案1】:

    之所以有效,是因为它们返回相同,两种解决方案都返回 sol。只是第二个直接返回变量sol,而第一个返回函数的输出(与作为参数传递的变量sol相同)。

    【讨论】:

    • 是的,但我的问题是变量 sol 已经在之前的调用中定义了一个较短的列表,为什么它不会通过例如 n = 15 哪个解决方案是 [8, 1 , 15, 10, 6, 3, 13, 12, 4, 5, 11, 14, 2, 7, 9] 在第一次调用 [8, 1, 15, 10, 6, 3, 13, 12, 4, 5 , 11, 14, 2, 7,9] 然后 [8, 1, 15, 10, 6, 3, 13, 12, 4, 5, 11, 14, 2,7] ecc... 直到 [ ] ?
    • 在第一种情况下,我定义了一个变量,该变量在每次调用时都会被 right 变量 sol 覆盖。在第二种情况下,我没有这样做。
    【解决方案2】:

    为了扩展另一个答案,只有一个列表对象sol 被传递并返回。它从来没有被复制过。这是另一个强调这一点的解决方案。这里sol 不是任何地方的参数,它只是取自闭包,内部函数只返回布尔值。

    def square_sums_row(n):
        sol = []
    
        def recurse(s):
            if s == []:
                return True
            for i, x in enumerate(s):
                if is_valid(x):
                    sol.append(x)
                    iterate = recurse(s[:i] + s[i + 1:])  ###########
                    if iterate:  ###########
                        return True
                    sol.pop(-1)
            return False
    
        def is_valid(x):
            if len(sol) == 0:
                return True
            if ((sol[-1] + x) ** 0.5) % 1 == 0:
                return True
            return False
    
        if recurse([x for x in range(1, n + 1)]):
            return sol
        else:
            return False
    
    

    【讨论】:

    • 啊,好吧,我想我明白了……对象是独一无二的,我认为每次迭代都会创建一个新对象。为此,我必须明确复制变量对吗?谢谢!
    • @Tortar 确切地说,或通过其他方式创建一个新列表,例如切片或+,就像你对s所做的那样。
    猜你喜欢
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 2023-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多