【发布时间】:2020-11-02 02:45:54
【问题描述】:
一个朋友给我这个问题作为挑战,我试图在 LeetCode 上找到这样的问题,但遗憾的是找不到。
问题
给定从 1 到 N 编号的一行人,以及一组 M 对敌人的列表,找出不包含两个敌人的人的子行总数。
例子:
N = 5, enemies = [[3,4], [3,5]]答案:
9解释:这些连续的子区间是:
[1,1], [2,2], [3,3], [1,2], [2,3], [1,3], [4,4], [4,5], [5,5]
我的方法
我们将非冲突区间定义为从(包括)[a,b] 的连续区间,在该区间内没有两个人是敌人。
向后工作,如果我知道[1,3] 有一个非冲突区间,就像上面给出的示例一样,我知道这两个数字之间的连续区间数是@987654327@,其中n 是间隔。在这种情况下,间隔长度为3,因此在[1,3] 之间(包括)之间存在6 间隔。
扩展这个逻辑,如果我有一个所有非冲突区间的列表,那么答案就是每个区间长度n_i 的(n_i*(n_i+1))/2 的总和。
然后我需要做的就是找到这些间隔。 这是我卡住的地方。
我真的想不出类似的编程问题。这看起来很相似,但与 leetcode 上的Merge Intervals 问题所要求的相反。在那个问题中,我们被赋予了好的间隔,并被要求将它们组合起来。在这里,我们得到了不好的结果。
有什么指导吗?
编辑:我能想到的最好的:
这行得通吗?
所以让我们将max_enemy[i] 定义为小于特定人i 的最大敌人,其中i 是通常的[1,N]。我们可以在O(M) 时间内生成这个值,只需使用以下循环:
max_enemy = [-1] * (N+1) # -1 means it doesn't exist
for e1, e2 in enms:
e1, e2 = min(e1,e2), max(e1, e2)
max_enemy[e2] = max(max_enemy[e2], e1)
然后,如果我们通过保持滑动窗口的人的数组。一旦我们找到一个人i 拥有:max_enemy[i] < i,滑动窗口就会结束。这样我们就知道包括这个人会打破我们的连续间隔。所以我们现在知道我们的区间是[s, i-1],我们可以进行数学计算。我们重置s=i 并继续。
这是如何在视觉上工作的可视化。我们在任意两个敌人之间画一条路径:
N=5, enemies = [[3,4], [3,5]]
1 2 3 4 5
| | |
-----
| |
--------
EDIT2:我知道这对N=5, enemies=[[1,4][3,5]] 不起作用,目前正在修复,仍然卡住
【问题讨论】:
-
我无法推理您的示例、解释和答案...为什么答案是 9?
-
不,它必须是连续的,所以
[1,3]是不可能的。我添加了更多解释 -
对不起,我在考虑子数组,我猜子数组
[1,2,3]相当于区间[1,3]。将更新问题 -
@Emma 用我的(破碎的)方法更新了问题
标签: algorithm math sliding-window