#3605
Hard Algorithms Minimum stability factor of array
Array Math Binary Search Greedy Segment Tree Number Theory
20.3% acceptance
Feb 25, 2026
41
2
You are given an integer array nums and an integer maxC.
A subarray is called stable if the highest common factor (HCF) of all its elements is greater than or equal to 2.
The stability factor of an array is defined as the length of its longest stable subarray.
You may modify at most maxC elements of the array to any integer.
Return the minimum possible stability factor of the array after at most maxC modifications. If no stable subarray remains, return 0.
Note:
The highest common factor (HCF) of an array is the largest integer that evenly divides all the array elements.
A subarray of length 1 is stable if its only element is greater than or equal to 2, since HCF([x]) = x.
Solution
Rust
Time O(n²)
Space O(n)
impl Solution {
pub fn min_stable(nums: Vec<i32>, max_c: i32) -> i32 {
let n = nums.len();
let max_c = max_c as usize;
// Build sparse table for range GCD
let log2 = {
let mut lg = vec![0usize; n + 1];
for i in 2..=n { lg[i] = lg[i / 2] + 1; }
lg
};
let levels = log2[n] + 1;
let mut sparse = vec![nums.clone(); levels];
for k in 1..levels {
let len = 1 << (k - 1);
for i in 0..n {
if i + len < n {
sparse[k][i] = Self::gcd(sparse[k-1][i], sparse[k-1][i + len]);
} else {
sparse[k][i] = sparse[k-1][i];
}
}
}
let range_gcd = |l: usize, r: usize| -> i32 {
// inclusive [l, r]
if l == r { return sparse[0][l]; }
let k = log2[r - l + 1];
Self::gcd(sparse[k][l], sparse[k][r + 1 - (1 << k)])
};
// Check if stability factor <= L is achievable with max_c changes
// For L=0: count elements >= 2
// For L>=1: greedy with windows of size L+1
let feasible = |l: usize| -> bool {
if l == 0 {
let cnt = nums.iter().filter(|&&x| x >= 2).count();
return cnt <= max_c;
}
let win = l + 1; // window size
if win > n { return true; }
let mut count = 0usize;
let mut i = 0usize;
while i + win <= n {
if range_gcd(i, i + win - 1) >= 2 {
count += 1;
if count > max_c { return false; }
i += win; // break at rightmost position, skip past it
} else {
i += 1;
}
}
true
};
// Binary search: find minimum L in [0..=n] where feasible(L)
let mut lo = 0usize;
let mut hi = n;
while lo < hi {
let mid = (lo + hi) / 2;
if feasible(mid) {
hi = mid;
} else {
lo = mid + 1;
}
}
lo as i32
}
fn gcd(a: i32, b: i32) -> i32 {
if b == 0 { a } else { Self::gcd(b, a % b) }
}
}