Python 解析一个";“订购”;列出并找到各自的总和和加数?

Python 解析一个";“订购”;列出并找到各自的总和和加数?,python,algorithm,list,sum,stack,Python,Algorithm,List,Sum,Stack,抱歉,如果以前有人问过这个问题,但我已经搜索了几天,没有找到与我的问题相关的帮助 我试图研究的是一种解析列表(类似于预算表)并将索引分配给父级或子级的方法。父项是其子项的总和,子项是该父项的加数(或没有父项的数字) 例如:[1,2,3,6],其中6是1、2和3的父项 或者更复杂的例子:[1,2,3,6,1,4,3,8,14,3,2,3,8,1,4,3,8,16,30] 30是这个列表的“根”,因为30=14+16、14=6+8、6=1+2+3等等。这个列表总是有一定的顺序,也就是说,孩子们总是一

抱歉,如果以前有人问过这个问题,但我已经搜索了几天,没有找到与我的问题相关的帮助

我试图研究的是一种解析列表(类似于预算表)并将索引分配给父级或子级的方法。父项是其子项的总和,子项是该父项的加数(或没有父项的数字)

例如:
[1,2,3,6]
,其中6是1、2和3的父项

或者更复杂的例子:
[1,2,3,6,1,4,3,8,14,3,2,3,8,1,4,3,8,16,30]

30是这个列表的“根”,因为30=14+16、14=6+8、6=1+2+3等等。这个列表总是有一定的顺序,也就是说,孩子们总是一起出现在他们的父母之前(当然,当父母是另一个父母的孩子时除外)。我试图找到最有效的方法,我的两个解决方案使用堆栈,但它们不是100%正确,因为上面的两个示例都失败了。以下是两者的伪代码:

解决方案尝试1

stack = []
for number in list
    if stack.isEmpty()
        stack.push(number)
    elif stack.peek() > number
        stack.push(number)
    else
        copy = stack
        temp = []
        current = number
        while current > 0
            popped = copy.pop()
            temp.push(popped)
            current -= popped
        if current == 0
            while temp
                child = temp.pop()
                child.parent = number
            stack = copy
    stack.push(number)
解决方案尝试2

stack = []
for number in list
    stack.push(number)

while stack.size() > 1
    child = stack.pop()
    copy = stack
    temp = []
    if child > stack.peek()
        while current > 0 and copy.size() > 0
            popped = copy.pop()
            temp.push(popped)
            current -= popped    
        if current == 0
            while temp
                child = temp.pop()
                child.parent = number
任何想法或想法都将不胜感激。这时我的头撞到了墙上

编辑

复杂示例解决方案
[1,2,3,6,1,4,3,8,14,3,2,3,8,1,4,3,8,16,30]

                   30
            /             \
      14                     16
    /      \              /        \
  6          8           8             8
/  |  \   /  |  \     /  |   \     /   |   \
1  2   3  1  4   3   3   2    3   1    4    3

这是一个有趣的问题。下面是一个使用列表作为树的递归解决方案(根在索引0处,子在以下索引处):

get_tree
的逻辑如下:

  • 在迭代数字列表时收集树列表
  • nums
    中的每个位置,您可以执行以下两项操作之一:
    • 取树列表末尾的树的任何后缀(
      trees[i://code>),并将它们作为子树放在一个新树下,当前编号为根
    • 将当前编号作为新树添加到堆栈中
  • 当您到达列表的末尾并且堆栈上只有一棵树时,这就是结果
基本上,您将获得一个后序遍历,并从中生成所有可能的树,从而剔除沿途存在和不匹配的树。对于正整数,此过程是确定性的,即,要么只有一个有效树,要么没有有效树。对于非正整数,可能存在多个可能的有效树。简单的例子是一个只有零的列表,其中任何树都是有效的。

另一个解决方案:

如果您的输入按上述方式排序,则可以利用
sorted()
函数和递归

示例(假设输入为非空):

印刷品:

[30, [[14, [[6, [1, 2, 3]], [8, [1, 4, 3]]]], [16, [[8, [3, 2, 3]], [8, [1, 4, 3]]]]]]
[3, [1, 2]]
[6, [1, 2, 3]]
[7, []]

为什么30是列表的根?你能编辑你的问题并发布一些示例输入和预期输出吗?30是“根”父级,因为它是所有其他父级的总和。请参见EDIT。您能为这个复杂的示例提供完整的解释吗?我看到1+2+3=6,但你如何将1,4,3,8,14分组…?你假设所有整数都是正整数吗?可能存在负整数/双精度的边缘情况,但大多数情况下,列表都是正整数。这样的序列是标准的吗,即,有没有唯一的解决方案?如果是,他们肯定有名字。@Vromfondel不确定我是否理解正确。序列是树的后序遍历。通常,多棵树可以生成相同的后序遍历序列。因此,解决方案是否唯一取决于施加的限制。在这种情况下,仅求和限制是不够的(请参见零示例)。但是,对于严格意义上的正数,它应该是,即使我没有正式证明:)
def _get_tree(lst):   
    new_children, cnt = [], 0
    for idx, v in sorted(enumerate(lst[:-1]), key=lambda k: k[1], reverse=True):
        cnt += v
        new_children.append((idx, v))

        if cnt == lst[-1]:
            start, new_children = 0, sorted(new_children, key=lambda k: k[0])
            for idx2, v2 in new_children:
                if idx2 - start == 0:
                    yield lst[start]
                else:
                    yield [v2, [*_get_tree(lst[start:idx2+1])]]
                start = idx2 + 1
            break

def get_tree(lst):
    return list([lst[-1], [*_get_tree(lst)]])

print(get_tree([1,2,3,6,1,4,3,8,14,3,2,3,8,1,4,3,8,16,30]))
print(get_tree([1, 2, 3]))
print(get_tree([1, 2, 3, 6]))
print(get_tree([1, 2, 3, 7]))
[30, [[14, [[6, [1, 2, 3]], [8, [1, 4, 3]]]], [16, [[8, [3, 2, 3]], [8, [1, 4, 3]]]]]]
[3, [1, 2]]
[6, [1, 2, 3]]
[7, []]