python - 这些元组可以以某种方式排列吗?

标签 python sorting data-structures tuples pseudocode

我正在编写一个程序,以将元组列表作为输入,并根据它们是否可以以某种方式排列来返回一些内容。通常我在编码之前就知道如何解决问题,但在这种情况下,我很难想出一个好的方法来解决这个问题。
这个想法是输入一个这样的列表.. [(5, 2), (3, 5), (3, 3), (1, 3)] 并验证是否可以以某种方式排列,以便最后number 匹配下一个元组的开头。所以在这种情况下是可能的,比如:[(1, 3), (3, 3), (3, 5), (5, 2)]。于是验证为真。元组也可以颠倒。
我想遍历列表并将有效的元组对组合在一起,但是如果它们没有以正确的方式分组以与其余的对一起工作怎么办?也可能太费时间了。
有任何想法吗?
谢谢!

最佳答案

正如评论中提到的,这相当于找到一个 Hamiltonian path在元组元素的图中,元组之间的有向边与匹配的第一个和最后一个元素。虽然它是一个 NP 完全问题(哈密顿路径,我不知道对你的问题采取不同的方法是否可以使它更容易),但很容易为它想出蛮力算法。这是一个相当幼稚的递归实现:

def chained_list(lst):
    # List of rearranged elements
    chain = []
    # Flags to tell whether each item has been picked already
    picked = [False] * len(lst)
    # Loop to add all possible first elements (so the recursive function
    # can work on the assumption that there is a previous element)
    for i, item in enumerate(lst):
        # Add first element
        chain.append(item)
        # Mark as picked
        picked[i] = True
        # Attempt recursion
        _chain_list_rec(lst, picked, chain)
        # If we got a rearranged list finish
        if len(chain) == len(lst):
            return chain
        # Otherwise remove the selected first element
        picked[i] = False
        chain.pop()
    raise ValueError('cannot chain list')

def _chain_list_rec(lst, picked, chain):
    # Take previous value to match
    _, prev = chain[-1]
    # Iterate through items
    for i, (item, p) in enumerate(zip(lst, picked)):
        # If item is available and matches previous value
        if not p and item[0] == prev:
            # Add it and mark it as picked
            chain.append(item)
            picked[i] = True
            # Try remaining recursion
            _chain_list_rec(lst, picked, chain)
            # Check if we finished
            if len(chain) == len(lst):
                return
            # Undo adding if not finished
            picked[i] = False
            chain.pop()

print(chained_list([(5, 2), (3, 5), (3, 3), (1, 3)]))
# [(1, 3), (3, 3), (3, 5), (5, 2)]
print(chained_list([(5, 2), (3, 3), (1, 3)]))
# ValueError: cannot chain list
您可以尝试以不同的方式改进它,例如使用 multiset而不是列表和 picked标志列表(假设您想支持重复元素,否则 set 可以),使用其他数据结构更快地搜索链中的下一个潜在项目(例如,一个 dict 以第一个元素为键并为多集赋值以该元素开头的元组),或添加完成检查(在递归开始时检查 len(chain) == len(lst) 以保存最后一步的循环)。您还可以在递归的每一步检查当前部分解决方案的可行性。请注意,对于任何部分解决方案: a) 必须至少有一项以 prev 开头(chain 中最后一项的第二个值) b) 对于任何给定的值 k ,以 k 开头的可用元组数通常必须等于以 k 结尾的可用元组的数量,调整为 k == prev并注意最多可以有一个 k其中有一个额外的元组以 k 结束(这将是最后一个)。如果这些条件不成立,那么该递归路径是不可行的。您可能会想到其他方法来提高效率。然而,在任何情况下,算法在某一点或另一点执行都将变得非常昂贵,因此请记住,这种方法仅适用于相对较小的输入。

关于python - 这些元组可以以某种方式排列吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62519477/

相关文章:

python - Dijkstra算法随机选择具有相同最小权重的相邻节点

c - 为结构中的变量分配内存的最佳方法是什么?

python - 嵌套的 for-while 循环在第一次运行后停止迭代

c++ - 按 'enveloping' 或 'dominance' 标准排序坐标

delphi - 如何设置 TDBGrid 排序中的字符顺序?

javascript - 如何防止自动排序对象数字属性?

algorithm - 如果第一个源节点出队后队列已经为空,广度优先搜索如何工作?

c++ - 使用 BER 编码和解码 ASN.1 REAL

python - 如何使用 TensorFlow 将预测值添加到 CSV 文件中的空列?

python - 关于斐波那契数列生成器的问题 - 没有打印任何内容