Minimum Component Subset — Problem Statement & Solution Guide

Two PointersMediumMixed
TimeO(n)
|
SpaceO(k)

Quick Answer & Algorithm Key Takeaway

Master coding challenges related to Two Pointers and solve the Minimum Component Subset problem optimally.

TopicTwo Pointers
PatternMixed
TimeO(n)
SpaceO(k)

Problem Description

Given an integer array nums and a set required of distinct integers, find the length of the shortest contiguous subarray of nums that contains every element of required at least once. If no such subarray exists, return -1. The input consists of the array nums and the set required; the output is a single integer representing the minimal length or -1 when impossible.

DSA Pattern Breakdown

DSA Pattern Breakdown

"Minimum Component Subset"

medium

WHY DOES IT MATTER?

Sliding‑window is essential for any problem that asks for the smallest/largest contiguous segment meeting a condition, because it converts an exponential search into a linear scan by exploiting the monotonic nature of the condition.

OPTIMIZATION CHALLENGE

The key insight is that you only need to track counts of required elements, not the entire window content, allowing O(1) updates per pointer move and preventing repeated full‑window scans.

REAL-WORLD CONNECTION

Think of a streaming log processor that must detect the shortest time window containing all critical error codes; the two‑pointer technique mirrors how the processor slides a time cursor forward and backward to pinpoint the minimal interval.

During an interview, first write the frequency map for required elements, then implement the expand‑contract loop; keep a variable for how many distinct required values are satisfied to avoid scanning the whole map each time.

COMPLEXITY AT A GLANCE

⏱ Time:O(n)
💾 Space:O(k)

Core Theory — Why This Approach?

The problem is a classic sliding‑window (two‑pointer) scenario where we need to maintain a dynamic interval of the array that satisfies a coverage constraint – containing every element from the required set at least once. A naive solution would enumerate all O(n²) subarrays and check each for the presence of required elements, leading to prohibitive runtime for large n. The optimal paradigm treats the left and right pointers as the current window boundaries and expands the right pointer until the window becomes valid, then contracts the left pointer to shrink it while preserving validity, updating the best length along the way. This approach leverages a frequency map of required elements, allowing O(1) updates per movement and guaranteeing each element is processed at most twice, yielding linear time.

The underlying theory rests on the monotonicity of the window: once a window satisfies the requirement, any extension to the right will also satisfy it, and any contraction from the left may break it. By exploiting this property we can avoid re‑examining previously processed sections, which is the essence of the two‑pointer technique. The algorithm thus transforms a combinatorial search into a deterministic scan, achieving O(n) time and O(k) auxiliary space, where k is the size of the required set.

Interview Questions on This Problem

Q1How would you modify the solution if the required set could contain duplicate values, i.e., you need each value a specific number of times?

Maintain a target count map for each required value and a current count map in the window. The window is valid only when every value's current count meets or exceeds its target count. The rest of the sliding‑window logic stays the same.

Q2Can you solve the problem in a single pass without using an explicit hash map for frequencies?

If the range of possible values is small and dense (e.g., 0…M), you can use a fixed‑size integer array as a frequency counter, which acts like a hash map but with O(1) access and no hashing overhead.

Q3What is the time‑space trade‑off if you pre‑process the array to store the next occurrence index of each required element?

Pre‑processing with a map of positions allows a binary‑search‑based solution that runs in O(n log k) time and O(n) space, which is slower than the linear two‑pointer method but can be useful when multiple queries on the same array are required.

Examples

Example 1

Input

nums = [4,2,1,5,2,3,1,2], required = [1,2,3]

Output

3

Explanation: The subarray from index 4 to 6 (0‑based) is [2,3,1] and includes 1, 2, 3. No shorter window can contain all three values, so the answer is 3.

Example 2

Input

nums = [7,5,9,1,2,8,6], required = [3,4]

Output

-1

Explanation: Neither 3 nor 4 appears in nums, therefore no contiguous segment can satisfy the requirement; the function returns -1.

Example 3

Input

nums = [10,12,5,6,12,5,7,5,6], required = [5,6,12]

Output

3

Explanation: The segment from index 1 to 3 is [12,5,6] and already contains 5, 6, 12. Any window shorter than length 3 would miss at least one required value, so the minimal length is 3.

Constraints

  • 1 <= nums.length <= 100000
  • 1 <= required.size <= 100000
  • -1000000000 <= nums[i] <= 1000000000
  • All values in required are distinct

Optimal Approach & Strategy

Use two pointers with a hash map to maintain counts of required elements, expanding right until the window is valid then contracting left to minimize it – O(n) time.

Brute Force Approach

Check every possible subarray, count required elements inside each, and keep the smallest length that satisfies the condition – O(n²) time.

Code Solutions

JavaScript Solution
Time: O(n)
function minComponentSubset(nums, required) {
    const need = new Map();
    for (const x of required) need.set(x, 0);
    const requiredCount = need.size;
    const window = new Map();
    let have = 0, left = 0, best = Infinity;
    for (let right = 0; right < nums.length; ++right) {
        const val = nums[right];
        if (need.has(val)) {
            window.set(val, (window.get(val) || 0) + 1);
            if (window.get(val) === 1) have++;
        }
        while (have === requiredCount && left <= right) {
            best = Math.min(best, right - left + 1);
            const lval = nums[left];
            if (need.has(lval)) {
                window.set(lval, window.get(lval) - 1);
                if (window.get(lval) === 0) have--;
            }
            ++left;
        }
    }
    return best === Infinity ? -1 : best;
}

// Driver (same format as template)
const fs = require('fs');
const data = fs.readFileSync(0,'utf8').trim().split(/\s+/).map(Number);
let idx = 0;
const n = data[idx++];
const nums = data.slice(idx, idx+n); idx+=n;
const m = data[idx++];
const required = data.slice(idx, idx+m);
console.log(minComponentSubset(nums, required).toString());

Asked in Top Tech Interviews

FlipkartZomato

Solve in Interative Editor

Ready to test your code? Open our built-in compiler, run custom test suites, and see detailed complexity analysis reports instantly.