【问题标题】:Converting subset sum algorithm from JavaScript to Python将子集和算法从 JavaScript 转换为 Python
【发布时间】:2020-04-01 21:02:14
【问题描述】:

我在 JavaScript 中有以下代码来计算数组中总和等于 n 的最小元素:

function findMinSum(arr, n){
    if(!arr) return 
    let min 
    for (let i=0; i<arr.length; i++) {

        /* if a number equals the sum, it's obviously
         * the shortest set, just return it
         */
        if (arr[i] == n) return [arr[i]]     

        /* recursively call on subset with
         * sum adjusted for removed element 
         */
        let next = findMinSum(arr.slice(i+1), n-arr[i])

        /* we only care about next if it's shorter then 
         * the shortest thing we've seen so far
         */
        if (next){
            if(min === undefined || next.length < min.length){
                min = [arr[i], ...next]
            }
        }
    }
    return min && min  /* if we found a match return it, otherwise return undefined */
}

我从here 得到这个代码。

我想将其转换为 Python,所以我做了以下操作:

def findMinSum(arr, n):
    if not arr:
        return

    min = []
    min_len = len(min)
    for i in range(0, len(arr)):

        if(arr[i] == n):
            return (arr[i])

        next = []
        next = findMinSum(arr[i+1:], n-arr[i])

        if(next == list):
            next_len = len(next)
        else:
            next_len = next

        if(next):
            print(next) # printing next for debugging purpose 
            if( ( not min ) or (next_len < min_len) ):
                min = [ next, arr[i]]

    return min

arr = [8, 6, 1, 5, 9, 3]
get_min = findMinSum(arr, 14)

print(get_min)

但是当我运行这段代码时,我得到了以下错误:

3
[3, 1]
9
[[3, 1], 6]
3
[3, 9]
Traceback (most recent call last):
  File "test1.py", line 34, in <module>
    min2 = findMinSum(arr, 14)
  File "test1.py", line 25, in findMinSum
    if( ( not min ) or (next_len < min_len) ):
TypeError: '<' not supported between instances of 'list' and 'int'

预期的输出应该是[8, 6][9, 5]

我想不出任何其他方式来编写代码,因为我是 Python 的新手。另外我不想导入除 numpy 之外的任何其他模块。

我的翻译哪里出错了?

【问题讨论】:

  • 欢迎来到 SO! if(next == list): 中的 list 是什么?建议不要使用 list next 或其他内置变量名称。此外,请跳过 Python 中的 ()s 以获取条件和返回值。你可能不小心创建了元组。
  • @ggorlen 谢谢!我正在检查下一个是否是列表。此外,我尝试更改变量名称,但我得到相同的输出。
  • 那行不通——你想在这里isinstancetype。是的,next 是一个迭代器函数,所以我只是在写一个一般性的评论,而不是一个解决方案。缓存len 调用也是不好的做法,这可能是原因:min_len = len(min)。当min 更改时,这永远不会更新。 min 也覆盖了内置函数 min
  • 顺便说一句,答案不应该是 6、9、3 吗?
  • @ggorlen 感谢您的建议,我将尝试在我的代码中实现它们。

标签: javascript python python-3.x list


【解决方案1】:

这里有各种各样的问题。

  • 永远不要覆盖内置函数。 Python 定义了minnextlist。如果覆盖它们,您可能会遇到非常微妙的错误。
  • Python 没有数组,它有列表。永远不要缓存对 len 的调用——此代码不会更新 min_len = len(min),因此如果 min 曾经更新过,则该值在此循环中的未来比较中是陈旧的。
  • 避免在条件和返回语句周围使用不必要的括号,因为括号用于创建元组。 return (arr[i]) 应该是 return [arr[i]](单个元素列表)。
  • min = [ next, arr[i]][arr[i], ...next] 在排序或拆包/展开方面都不匹配。使用min = [arr[i], *next]next 展平。
  • JS 和 Python 以不同的方式处理 undefined/None 和布尔数组/列表值。 JS 将空数组视为真,而 Python 将空列表视为假。 min = [] 不会捕获隐式设置min = undefined 的原始JS 代码,因此if not min 会检查min 是否为空或空,这与原始JS 版本无法比较。
  • 无需检查类型;检查Nonenot None 就足够了。
  • if (next) { if (more stuff ... 可以只是一个使用and 的块。没有理由嵌套(这是原来的问题)。
  • 在大多数情况下,使用enumerate 而不是range 来迭代列表(如果您确实使用范围,range(0, len(some_list)) 可以是range(len(some_list))
  • 坚持PEP-8。使用 snake_case 来命名函数和变量。

这是我的重写:

def find_smallest_sum(lst, n):
    if not lst:
        return None

    smallest = None

    for i, e in enumerate(lst):
        if e == n:
            return [e]

        next_lst = find_smallest_sum(lst[i+1:], n - e)

        if next_lst is not None and (smallest is None or len(next_lst) < len(smallest)):
            smallest = [e, *next_lst]

    return smallest

if __name__ == "__main__":
    print(find_smallest_sum([10, 0, -1, 20, 25, 30], 59))  # => [10, -1, 20, 30]
    print(find_smallest_sum([8, 6, 1, 5, 9, 3], 14))       # => [5, 9]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    • 1970-01-01
    • 2013-09-23
    • 2022-01-14
    • 2018-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多