You are given two integers, n
and m
, and an array arr
of length n
where arr[i]
represents the position (1-indexed) that is set to 1 at step i+1
.
Initially, all positions from 1
to n
are set to 0.
At each step, you set arr[i]
to 1.
After each step, the array is split into groups of consecutive 1's.
Your task is to find the latest step (1-indexed) at which there exists a group of consecutive 1's of length exactly m
.
If no such group exists at any step, return -1
.
m
exists.
At first glance, it seems we could simulate the process step by step, updating the array and checking for groups of 1's of length m
after each update. However, this brute-force approach would be inefficient, especially for large n
, as it would require scanning the entire array after each step.
To optimize, we need a way to efficiently track the lengths of groups of 1's as we set positions to 1. Noticing that only the groups adjacent to the newly set position are affected, we can focus our updates and checks only on those areas.
This leads us to use a data structure (like a hash map or array) to record the length of groups at their boundaries. By updating only the affected boundaries, we can keep track of group sizes and efficiently determine if a group of length m
exists after each step.
lengths
of size n+2
to store the length of the group at each boundary (leftmost and rightmost points).m
currently exist.arr[i]
to 1, check the length of the group to the left and right (using lengths
at pos-1
and pos+1
).lengths
to reflect the new group size.m
are merged or split, update the counter accordingly.m
, record the current step as a candidate for the answer.
Example:
arr = [3,5,1,2,4]
, n = 5
, m = 1
Output: 3
At step 3, there was at least one group of size 1. After that, no such group exists.
The optimized approach is efficient and suitable for large inputs.
class Solution:
def findLatestStep(self, arr, m):
n = len(arr)
if m == n:
return n
lengths = [0] * (n + 2)
count = [0] * (n + 2)
res = -1
for step, pos in enumerate(arr):
left = lengths[pos - 1]
right = lengths[pos + 1]
group_len = left + right + 1
lengths[pos - left] = lengths[pos + right] = group_len
count[left] -= 1
count[right] -= 1
count[group_len] += 1
if count[m] > 0:
res = step + 1
return res
class Solution {
public:
int findLatestStep(vector<int>& arr, int m) {
int n = arr.size();
if (m == n) return n;
vector<int> lengths(n + 2, 0);
vector<int> count(n + 2, 0);
int res = -1;
for (int step = 0; step < n; ++step) {
int pos = arr[step];
int left = lengths[pos - 1];
int right = lengths[pos + 1];
int group_len = left + right + 1;
lengths[pos - left] = lengths[pos + right] = group_len;
count[left]--;
count[right]--;
count[group_len]++;
if (count[m] > 0) res = step + 1;
}
return res;
}
};
class Solution {
public int findLatestStep(int[] arr, int m) {
int n = arr.length;
if (m == n) return n;
int[] lengths = new int[n + 2];
int[] count = new int[n + 2];
int res = -1;
for (int step = 0; step < n; step++) {
int pos = arr[step];
int left = lengths[pos - 1];
int right = lengths[pos + 1];
int groupLen = left + right + 1;
lengths[pos - left] = lengths[pos + right] = groupLen;
count[left]--;
count[right]--;
count[groupLen]++;
if (count[m] > 0) res = step + 1;
}
return res;
}
}
var findLatestStep = function(arr, m) {
const n = arr.length;
if (m === n) return n;
const lengths = new Array(n + 2).fill(0);
const count = new Array(n + 2).fill(0);
let res = -1;
for (let step = 0; step < n; step++) {
const pos = arr[step];
const left = lengths[pos - 1];
const right = lengths[pos + 1];
const groupLen = left + right + 1;
lengths[pos - left] = lengths[pos + right] = groupLen;
count[left]--;
count[right]--;
count[groupLen]++;
if (count[m] > 0) res = step + 1;
}
return res;
};
The key insight for solving the "Find Latest Group of Size M" problem is to efficiently track group sizes at their boundaries using an auxiliary array. By updating only the affected group boundaries and maintaining a count of groups of size m
, we avoid unnecessary rescanning and achieve an optimal O(n) solution. This approach elegantly balances correctness and efficiency, making it suitable for large input sizes and demonstrating the power of boundary-based group tracking in array problems.