给定有序对(跳数)的子列表列表,我如何计算通过列表的路径数(每个路径都是跳数序列)
Posted
技术标签:
【中文标题】给定有序对(跳数)的子列表列表,我如何计算通过列表的路径数(每个路径都是跳数序列)【英文标题】:Given a list of sublists of ordered pairs (hops), how can I count the number of paths through list (each path is a sequence of hops) 【发布时间】:2020-08-09 00:57:00 【问题描述】:我有一个有序对列表[[(1,2), (3,3), (7,5)],[(2,3), (3,2), (6,4), (2,4)]]
(不一定是 2 个子列表)。每个有序对对应于一个有效路径(例如,对于 (1,2),从节点 1 到节点 2),每个子列表对应一个级别。我想通过一个列表找到路径的数量,这样我总是遵循一个有序的对路径。
对于上面的示例,(1,2), (2,3)
、(1,2), (2,4)
和 (3,3), (3,2)
都是有效路径。因此,程序将输出 3。
我正在考虑对每个列表的第二个值进行散列,关键是左对的数量 (2: 1, 3: 1, 5:1
),但这似乎相当低效,因为我必须以某种方式根据上一次列表迭代的key出现在当前列表迭代的值中。
看起来类似于图遍历问题,但 DFS 需要很大的空间复杂度(计算有序对的函数一次返回一个子列表,而不是完整列表)。
【问题讨论】:
你不能使用(2, 3), (3, 2)
之类的东西,对吧?每个子列表中的一对?
@MarkMoretto 否。它是子列表中的一个。我喜欢把它想象成街道车道上的节点,一个人必须过马路并且只能向前跳跃。
试试这个:[f"x, y" for x in pairs[0] for y in pairs[i] if x[1] == y[0]]
。或者,如果你不能使用 f 字符串,[[x, y] for x in pairs[0] for y in pairs[i] if x[1] == y[0]]
那是一个 f-string。 TBH,我并没有真正看到 Python 2.7 标记,但它只是每个子列表中的一对。
@MarkMoretto 它将如何扩展到 2 个以上的子列表
【参考方案1】:
[注意:由于您没有明确说明您想要什么输出,我假设您想要来自给定子列表的可能路径的总数]。
有趣的是,这个问题不需要图知识来解决。您可以使用普通的算法知识来解决这个问题(我用来解决问题的方法称为动态规划)。
首先让我打破这种方法:
-
为简单起见,我们举一个简单的例子:
let, input = [[(1, 2), (4, 2)], [(2, 3)]]
Now, let's think about, how many ways are there to reach node 3. Well,
there are (1, 2, 3) and (4, 2, 3), so two ways to reach 3.
-
现在,我们怎么能简单地表达,
the number of ways to reach 3
。
Note: reaching 3, requires the knowledge of reaching 2.
So, we'll try to express the number of reaching 3 in terms of reaching 2.
And, knowledge of number of reaching 2 can be obtained from previous
level's information. We can say like below:
If there is a pair (u, v), then, pres_ways[v] += prev_ways[u].
Here, "pres_ways[x]" denotes, present level's ways of reaching "any node x"
and "prev_ways[x]" denotes, previous level's ways of reaching "any node x"
我希望,您现在已经清楚了上面的概念。如果没有再读,因为我们会用它来解决问题。
现在,我们只需要找出起始状态。对于第一级,输入1
和4
的方式是one
,但是输入2
或3
是zero
。我希望你也清楚这一点。
现在,让我们编写解决方案:
# note: "ll" denotes lists of lists i.e. the input
# save your input in "ll"
# ll = [[(x, y)], [(u, v)]]
# let's assume, nodes are numbered from 1 to n
n = 7 # change the number as necessary or take input from file, as you wish
# initial state
prev = [0] * (n+1)
for u, v in ll[0]:
prev[u] = 1
for l in ll:
pres = [0] * (n+1)
for u, v in l:
pres[v] += prev[u]
prev = pres
tot = 0
for i in range(1, n+1):
tot += prev[i]
print("The number of ways to reach is ".format(i, prev[i]))
print("total: ".format(tot))
我希望解决方案是明确的,因为这只是我之前所说的反映。
I/O:
对于给定的输入:
ll = [
[(1, 2), (3, 3), (7, 5)],
[(2, 3), (3, 2), (6, 4), (2, 4)]
]
输出是:
The number of ways to reach 1 is 0
The number of ways to reach 2 is 1
The number of ways to reach 3 is 1
The number of ways to reach 4 is 1
The number of ways to reach 5 is 0
The number of ways to reach 6 is 0
The number of ways to reach 7 is 0
total: 3
此解决方案的复杂度为O(n * k)
,其中n
是节点数,k
是子列表数。
【讨论】:
@nii75435eoopy,它解决了你的问题吗?tot
变量包含您正在寻找的答案...它包含有效可能路径的总数...以上是关于给定有序对(跳数)的子列表列表,我如何计算通过列表的路径数(每个路径都是跳数序列)的主要内容,如果未能解决你的问题,请参考以下文章