You are given an integer n which represents an array nums containing the numbers from 1 to n in order. Additionally, you are given a 2D array conflictingPairs, where conflictingPairs[i] = [a, b] indicates that a and b form a conflicting pair.
Remove exactly one element from conflictingPairs. Afterward, count the number of non-empty subarrays of nums which do not contain both a and b for any remaining conflicting pair [a, b].
Return the maximum number of subarrays possible after removing exactly one conflicting pair.
Input: n =4, conflictingPairs =[[2,3],[1,4]]Output: 9Explanation:
* Remove `[2, 3]` from `conflictingPairs`. Now,`conflictingPairs = [[1, 4]]`.* There are 9 subarrays in`nums` where `[1, 4]`do not appear together. They are `[1]`,`[2]`,`[3]`,`[4]`,`[1, 2]`,`[2, 3]`,`[3, 4]`,`[1, 2, 3]` and `[2, 3, 4]`.* The maximum number of subarrays we can achieve after removing one element from `conflictingPairs`is9.
Input: n =5, conflictingPairs =[[1,2],[2,5],[3,5]]Output: 12Explanation:
* Remove `[1, 2]` from `conflictingPairs`. Now,`conflictingPairs = [[2, 5], [3, 5]]`.* There are 12 subarrays in`nums` where `[2, 5]` and `[3, 5]`do not appear together.* The maximum number of subarrays we can achieve after removing one element from `conflictingPairs`is12.
This straightforward method involves iteratively removing each conflicting pair from the list and then calculating how many valid subarrays remain for each case. For every possible removal, you check the number of subarrays that do not contain both elements of any remaining conflicting pair. While simple to implement, this approach is highly inefficient and does not scale well for large inputs.
Step 1:
For each position in the array, keep track of all conflicting pairs where that position is the right endpoint. This is done by building a right array, where right[r] contains all left endpoints that conflict with r.
Step 2:
Maintain two variables, left[0] and left[1], representing the most and second-most restrictive left endpoints seen so far. Also, create a bonus array to record the potential gain in valid subarrays if a particular conflict is removed.
Step 3:
Iterate through each position r in the array. For every left endpoint in right[r], update left to reflect the most restrictive endpoints. This helps determine the earliest start for a valid subarray ending at r.
Step 4:
For each position r, the number of valid subarrays ending at r is r - left[0]. Add this to the running total. For the most restrictive left endpoint, update bonus[left[0]] by adding left[0] - left[1], which represents the extra subarrays gained if that conflict is removed.
Step 5:
The final answer is the sum of the total valid subarrays and the maximum value in the bonus array, reflecting the best possible gain from removing a single conflicting pair.
classSolution {
publiclongmaxSubarrays(int n, int[][] conflictingPairs) {
List<List<Integer>> right =new ArrayList<>();
for (int i = 0; i <= n; i++) right.add(new ArrayList<>());
for (int[] p : conflictingPairs) {
int a = p[0], b = p[1];
right.get(Math.max(a, b)).add(Math.min(a, b));
}
long ans = 0;
long[] bonus =newlong[n + 1];
int[] left = {0, 0};
for (int r = 1; r <= n; r++) {
for (int l : right.get(r)) {
int[] candidates = {left[0], left[1], l};
Arrays.sort(candidates);
left[0]= candidates[2];
left[1]= candidates[1];
}
ans += r - left[0];
bonus[left[0]]+= left[0]- left[1];
}
long maxBonus = 0;
for (long b : bonus) maxBonus = Math.max(maxBonus, b);
return ans + maxBonus;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from typing import List
classSolution:
defmaxSubarrays(self, n: int, conflictingPairs: List[List[int]]) -> int:
right = [[] for _ in range(n+1)]
for a, b in conflictingPairs:
right[max(a, b)].append(min(a, b))
ans =0 left = [0, 0]
bonus = [0] * (n +1)
for r in range(1, n +1):
for l in right[r]:
left = sorted([left[0], left[1], l], reverse=True)[:2]
ans += r - left[0]
bonus[left[0]] += left[0] - left[1]
return ans + max(bonus)
impl Solution {
pubfnmax_subarrays(n: i32, conflicting_pairs: Vec<Vec<i32>>) -> i64 {
let n = n asusize;
letmut right =vec![Vec::new(); n +1];
for p in&conflicting_pairs {
let a = p[0] asusize;
let b = p[1] asusize;
right[a.max(b)].push(a.min(b));
}
letmut ans =0i64;
letmut left = [0usize, 0usize];
letmut bonus =vec![0i64; n +1];
for r in1..=n {
for&l in&right[r] {
letmut candidates =vec![left[0], left[1], l];
candidates.sort_by(|a, b| b.cmp(a));
left[0] = candidates[0];
left[1] = candidates[1];
}
ans += (r - left[0]) asi64;
bonus[left[0]] += (left[0] asi64- left[1] asi64);
}
ans +*bonus.iter().max().unwrap()
}
}
⏰ Time complexity: O(n + m). The algorithm iterates through all positions from 1 to n, and each of the m conflicting pairs is processed only once, making it efficient and not O(n * m).
🧺 Space complexity: O(n). Space usage is linear due to the right and bonus arrays, each with up to about 2n elements.