Find the Most Competitive Subsequence

medium monotonic stack greedy

Problem

You are given an integer array nums and an integer k. Pick exactly k elements from nums, keeping their original order, so that the chosen subsequence is the most competitive one possible. One subsequence beats another if, at the first index where they differ, it holds the smaller number — in other words, return the lexicographically smallest subsequence of length k.

The trick: scan left to right with an increasing stack. Pop a stack top whenever the new value is smaller and the elements still unread are enough to fill all k slots; only push while fewer than k elements have been kept.

Inputnums = [3, 5, 2, 6], k = 2
Output[2, 6]
Of all length-2 subsequences ([3,5], [3,2], [3,6], [5,2], [5,6], [2,6]), [2,6] starts with the smallest value, so it wins.

def most_competitive(nums, k):
    stack = []
    n = len(nums)
    for i, x in enumerate(nums):
        while stack and stack[-1] > x and len(stack) + (n - i) > k:
            stack.pop()
        if len(stack) < k:
            stack.append(x)
    return stack
function mostCompetitive(nums, k) {
  const stack = [];
  const n = nums.length;
  for (let i = 0; i < n; i++) {
    const x = nums[i];
    while (stack.length && stack[stack.length - 1] > x && stack.length + n - i > k) {
      stack.pop();
    }
    if (stack.length < k) stack.push(x);
  }
  return stack;
}
int[] mostCompetitive(int[] nums, int k) {
    int[] stack = new int[k];
    int top = 0, n = nums.length;
    for (int i = 0; i < n; i++) {
        int x = nums[i];
        while (top > 0 && stack[top - 1] > x && top + n - i > k) {
            top--;
        }
        if (top < k) stack[top++] = x;
    }
    return stack;
}
vector<int> mostCompetitive(vector<int>& nums, int k) {
    vector<int> stack;
    int n = nums.size();
    for (int i = 0; i < n; i++) {
        int x = nums[i];
        while (!stack.empty() && stack.back() > x && (int)stack.size() + n - i > k) {
            stack.pop_back();
        }
        if ((int)stack.size() < k) stack.push_back(x);
    }
    return stack;
}
Time: O(n) Space: O(k)