给定有序对(跳数)的子列表列表,我如何计算通过列表的路径数(每个路径都是跳数序列)

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"

我希望,您现在已经清楚了上面的概念。如果没有再读,因为我们会用它来解决问题。

现在,我们只需要找出起始状态。对于第一级,输入14的方式是one,但是输入23zero。我希望你也清楚这一点。

现在,让我们编写解决方案:


# 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 变量包含您正在寻找的答案...它包含有效可能路径的总数...

以上是关于给定有序对(跳数)的子列表列表,我如何计算通过列表的路径数(每个路径都是跳数序列)的主要内容,如果未能解决你的问题,请参考以下文章

EntityFrameworkCore.Sqlite - 如何使用包含给定列表的所有项目的子列表查询实体?

Prolog:获取包含给定整数的子列表

Leetcode--合并两个有序链表(21)

如何在C#中获取给定服务的子进程列表?

OpenGL在给定点列表的情况下计算正确的法线

Markdown语法