【问题标题】:GreedySorting in pythonpython中的贪心排序
【发布时间】:2015-03-19 12:00:04
【问题描述】:

我正在定义一个执行贪心排序的 Python 函数。
(生物信息学算法 I,2014,Coursera - Stepic 6.4

排序的结果应该是[+1, +2, +3, +4, +5],并且函数应该返回从初始输入列表的所有变化步骤。

要对初始输入列表进行排序,需要几个反转步骤。它很像pancake flipping problem。在这个问题中,有符号排列 ([-3,+4,+1,+5,-2]) 应更改为恒等符号排列 ([+1, +2, +3, +4, +5])。

示例输入:

 [-3, +4, +1, +5, -2]

样本输出:

[[-1, -4, +3, +5, -2],    
 [+1, -4, +3, +5, -2],    # -1  ->  +1
 [+1, +2, -5, -3, +4],    # reversal of (-4, +3, +5, -2)
 [+1, +2, +3, +5, +4],    # reversal of (-5, -3)
 [+1, +2, +3, -4, -5],    # reversal of (+5, +4)
 [+1, +2, +3, +4, -5],    # -4  ->  +4  
 [+1, +2, +3, +4, +5]]    # -5  ->  +5   Sorting finished!

我写了一个函数,但结果不正确。

# Implementation
def reversing(seq):
    """
    >>> reversing([+1,+2,-3,-4])
        [+4,+3,-2,-1]
    """
    seq.reverse()
    seq = map(lambda(x): -x, seq)
    return seq


def greedySorting1(lst):
    """
    ApproxReversalDistance (ARD)
    Return a number (ARD) until the result is [1,2,...,n]
    >>> greedySorting1([1,-5,3,-2,-4])
        6
    """
    change = []
    ARD = 0

    for i in range(len(lst)):
        if lst[i] != i+1:
            if i+1 in lst:
                id_i = lst.index(abs(i+1)) 
            else:
                id_i = lst.index(-abs(i+1))
            lst = lst[:i] + reversing(lst[i:id_i+1]) + lst[id_i+1:]
            ARD += 1
            change.append(lst)
        if lst[i] == -(i+1):
            lst[i] = i+1
            ARD += 1
            change.append(lst)

    return change   




# Testing
print greedySorting([-3,+4,+1,+5,-2])

    [[+1, -4, +3, +5, -2],    # Wrong: +1 should be -1
     [+1, -4, +3, +5, -2], 
     [+1, +2, -5, -3, +4], 
     [+1, +2, +3, +5, +4], 
     [+1, +2, +3, +4, -5],    # Wrong: +4 should be -4
     [+1, +2, +3, +4, -5], 
     [+1, +2, +3, +4, +5]]

如何修复我的代码以获得示例输出等正确答案?
谢谢。

【问题讨论】:

  • 基本上你的目标是获得([+1, +2, +3, +4, +5]) 作为输出并打印所有步骤直到达到这个目标?我们可以使用我们想要的一切吗?
  • 我可以得到最终的排序结果([+1, +2, +3, +4, +5]),但是我认为整个步骤可以解释这个问题中的贪心排序算法.

标签: python algorithm greedy


【解决方案1】:

当我解决了这个问题时,我发现用两个匹配的索引数组中的符号和数字来解决它要容易得多,并在每次迭代时制作列表和符号的副本以用作参考(不就运行时/内存分配而言,伤害和你想象的一样多。

另一件对您有帮助的事情是使用嵌套的 for 循环,以帮助您跟踪“反转”内的数字和符号的切换。

【讨论】:

  • 感谢您的回复。我认为我在 Python 中的列表复制中遗漏了一些重要概念。我必须了解更多。
【解决方案2】:

在这里您正在就地修改lst,因此change 中对它的任何引用都将反映相同的更改

if lst[i] == -(i+1):

您可以确保使用lst[:] 复制change 中的列表

for i in range(len(lst)):
    if lst[i] != i+1:
        if i+1 in lst:
            id_i = lst.index(abs(i+1)) 
        else:
            id_i = lst.index(-abs(i+1))
        lst = lst[:i] + reversing(lst[i:id_i+1]) + lst[id_i+1:]
        ARD += 1
        change.append(lst[:])
    if lst[i] == -(i+1):
        lst[i] = i+1
        change.append(lst[:])

现在你也可以简化这一行:

lst = lst[:i] + reversing(lst[i:id_i+1]) + lst[id_i+1:]

lst[i: id_i + 1] = reversing(lst[i: id_i + 1])

【讨论】:

  • 非常感谢您的帮助,约翰。
猜你喜欢
  • 2018-04-24
  • 2019-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-16
相关资源
最近更新 更多