A friend gave me this problem as a challenge, and I've tried to find a problem like this on LeetCode, but sadly could not.
Question
Given a line of people numbered from 1 to N, and a list of pairs of M enemies, find the total number of sublines with people that contain no two people that are enemies.
Example:
N = 5, enemies = [[3,4], [3,5]]
Answer:
9
Explanation: These continuous subintervals are:
[1,1], [2,2], [3,3], [1,2], [2,3], [1,3], [4,4], [4,5], [5,5]
My approach
We define a non-conflicting interval as a contiguous interval from (and including) [a,b]
where no two people are enemies in that interval.
Working backwards, if I know there is a non conflicting interval from [1,3]
like in the example given above, I know the number of contiguous intervals between those two numbers is n(n+1)/2
where n
is the length of the interval. In this case, the interval length is 3
, and so there are 6
intervals between (and including) [1,3]
that count.
Extending this logic, if I have a list of all non-conflicting intervals, then the answer is simply the sum of (n_i*(n_i+1))/2
for every interval length n_i
.
Then all I need to do is find these intervals. This is where I'm stuck.
I can't really think of a similar programming problem. This seems similar, but the opposite of what the Merge Intervals problem on leetcode asks for. In that problem we're sorta given the good intervals and are asked to combine them. Here we're given the bad.
Any guidance?
EDIT: Best I could come up with:
Does this work?
So let's define max_enemy[i]
as the largest enemy that is less that a particular person i
, where i
is the usual [1,N]
. We can generate this value in O(M)
time simply using a the following loop:
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)
Then if we go through the person's array keeping a sliding window. The sliding window ends as soon as we find a person i
who has: max_enemy[i] < i
. This way we know that including this person will break our contiguous interval. So we now know our interval is [s, i-1]
and we can do our math. We reset s=i
and continue.
Here is a visualization of how this works visually. We draw a path between any two enemies:
N=5, enemies = [[3,4], [3,5]]
1 2 3 4 5
| | |
-----
| |
--------
EDIT2: I know this doesn't work for N=5, enemies=[[1,4][3,5]]
, currently working on a fix, still stuck
[1,3]
is not possible. I added more explanation – QuantumHoneybees[1,2,3]
is equivalent to the interval[1,3]
. Will update the question – QuantumHoneybees