Python 按排列值顺序生成多个列表的所有排列
我已经研究了其他几个关于排列的问题,这个变体似乎没有出现。我正在寻找一种生成有偏排列的简单方法。这就是我的意思 假设我有两个列表(尽管我需要求解N个列表): 这些列表的排列看起来像[(a,d),(a,e),(a,f),(b,d),(b,e),(b,f)…]。然而,在我的世界里,排列的元素被打分并求和,以评估排列的价值。假设a,d和e得2分,b,c和f得1分。一些样本排列的值为:Python 按排列值顺序生成多个列表的所有排列,python,algorithm,Python,Algorithm,我已经研究了其他几个关于排列的问题,这个变体似乎没有出现。我正在寻找一种生成有偏排列的简单方法。这就是我的意思 假设我有两个列表(尽管我需要求解N个列表): 这些列表的排列看起来像[(a,d),(a,e),(a,f),(b,d),(b,e),(b,f)…]。然而,在我的世界里,排列的元素被打分并求和,以评估排列的价值。假设a,d和e得2分,b,c和f得1分。一些样本排列的值为: (a,d) = 4 (a,e) = 4 (a,f) = 3 (c,f) = 2 我需要生成所有置换,但我想在低值置
(a,d) = 4
(a,e) = 4
(a,f) = 3
(c,f) = 2
我需要生成所有置换,但我想在低值置换之前生成高值置换
假设每个列表的元素按降序排列,有没有一种好方法可以按值顺序生成排列
(显然,我可以生成所有置换并对它们进行排序,但我更愿意编写一个生成器,因为置换的数量可能会很大。)这应该很容易通过简单的贪婪式算法实现。也就是说,我假设您可以访问特定的值,而不仅仅是一个排序的值列表。还假设它是经过排序的
l1 = [(a, 2), (b, 1), (c, 1)]
l2 = [(d, 2), (e, 2), (f, 1)]
事实上,这是非常不平凡的,但下面是解决问题的方法(代码可能会在稍后出现,因为正如我所说的,它实际上是不平凡的)
假设在任何给定点有三种可能的操作:
next_entries: {*l1: last entry of l2 explored}
next_values: {*l1: l1 entry + next l2 entry}
在这一点上,可以进行上述三个可能点的计算。同样,可以生成代码,可能也可以,但可能需要20行密集的行才能以良好的可读性来完成。例如,让我们以l1={6,4,3,1}和l2={5,4,1}为例。将其绘制为二维平面上的水平线和垂直线 那么兴趣点都是交叉点。我们应该报告这些交点,以使从(inf,inf)移动到(0,0)的假想扫描线接触它们。请注意,位于水平线上的一个点不能早于位于同一条直线上的另一个更右的点进行报告。所以对于每一条水平线,我们必须只检查最右边的点。从所有这些点中,我们必须选择一个坐标和最大的点。这可以通过堆数据结构实现 最初,我们将位于最右侧垂直线上的所有点放入堆中。然后我们从堆中提取顶点,生成它,最后将它的左邻居放入堆中(如果它有一个)。所以堆总是包含最多len(l1)个元素,每个新生成的点都会消耗我们O(log(len(l1)))。若我们选择l1作为两个给定列表中的最小列表,则可以改进该解决方案 以下是示例解决方案:
import heapq
a = [("a", 6), ("b", 4), ("c", 3), ("d", 1)]
b = [("e", 5), ("f", 5), ("g", 4), ("h", 2)]
class Pair:
def __init__(self, i, j, value):
self.i = i
self.j = j
self.value = value
def __cmp__(self, other):
return other.value - self.value
def solution(a, b):
heap = []
for i in range(len(a)):
heapq.heappush(heap, Pair(i, 0, a[i][1] + b[0][1]))
while len(heap) > 0:
pair = heapq.heappop(heap)
yield (a[pair.i], b[pair.j], pair.value)
if pair.j + 1 < len(b):
heapq.heappush(heap, Pair(pair.i, pair.j + 1, a[pair.i][1] + b[pair.j + 1][1]))
for (a, b, value) in solution(a, b):
print ("%s %s -> %d" % (a, b, value))
导入heapq
a=[((“a”,6),(“b”,4),(“c”,3),(“d”,1)]
b=[(“e”,5),(“f”,5),(“g”,4),(“h”,2)]
类对:
定义初始值(self,i,j,value):
self.i=i
self.j=j
自我价值=价值
定义cmp(自身、其他):
返回other.value-self.value
def溶液(a、b):
堆=[]
对于范围内的i(len(a)):
heapq.heappush(堆,对(i,0,a[i][1]+b[0][1]))
当len(heap)>0时:
pair=heapq.heapop(堆)
产量(a[pair.i]、b[pair.j]、pair.value)
如果第j+1对%d”%(a、b、值))
当我们进入更高的维度时,情况会变得更糟(需要合并两个以上的列表)。它可以在2D解决方案的基础上通过记忆来解决,因此我们首先为l1、l2构建一个类似惰性列表的数据结构,然后再次应用相同的算法,将此记忆列表和l3作为参数,依此类推。必须采取的最后一步——我们应该始终使用长度较小的数组作为l1,或者在开始时不要将l1的所有元素推入堆中
完成N个列表的代码示例,因为它太长。为什么b在d之前?你还想要产品还是排列?应该(b,c)真的在列表中吗?我的理解是,你把两者混为一谈。投票结束,因为现在还不清楚你的预期是什么output@PadraicCunningham我在找排列。我修正了这个例子,现在看起来很清楚了。@SlaterTyranus是个打字错误,应该是c,f。列表是独立的,不应该混合。这听起来对我来说也是正确的方向。如果每个列表和副本的副本只包含该特定列表的最高未用尽值集(即本例中的所有2),该怎么办。在这种情况下,它意味着l1=[a]和l2=[d,e]。将为这些列表生成所有排列,然后弹出并填充具有下一个最低非空值集的列表。(在这种情况下,任意选择l1而不是l2,给出l1=[b,c]和l2=[d,e]。然后会为新的l1和l2等生成置换。我真的不明白这是如何工作的……什么是“l1的当前条目”如果我们迭代
l2
?那么,为什么我们在每个点上只有3个可能的操作?@quasiverse我认为解决方案甚至比这更复杂。无论如何,我的理解是,import heapq
a = [("a", 6), ("b", 4), ("c", 3), ("d", 1)]
b = [("e", 5), ("f", 5), ("g", 4), ("h", 2)]
class Pair:
def __init__(self, i, j, value):
self.i = i
self.j = j
self.value = value
def __cmp__(self, other):
return other.value - self.value
def solution(a, b):
heap = []
for i in range(len(a)):
heapq.heappush(heap, Pair(i, 0, a[i][1] + b[0][1]))
while len(heap) > 0:
pair = heapq.heappop(heap)
yield (a[pair.i], b[pair.j], pair.value)
if pair.j + 1 < len(b):
heapq.heappush(heap, Pair(pair.i, pair.j + 1, a[pair.i][1] + b[pair.j + 1][1]))
for (a, b, value) in solution(a, b):
print ("%s %s -> %d" % (a, b, value))