
Problem Statement
Given an integer array nums
and a positive integer k
, the task is to return the most competitive subsequence of nums
that has a size of k
. A subsequence in this context is formed by erasing some elements (possibly none) from the array such that the remaining elements preserve their original order. A subsequence a
is deemed more competitive than another subsequence b
, if, at the first point of difference, the element in a
is smaller than the corresponding element in b
. This problem involves identifying the lexicographically smallest subsequence of a given length from the array.
Examples
Example 1
Input:
nums = [3,5,2,6], k = 2
Output:
[2,6]
Explanation:
Among the set of every possible subsequence: {[3,5], [3,2], [3,6], [5,2], [5,6], [2,6]}, [2,6] is the most competitive.
Example 2
Input:
nums = [2,4,3,3,5,4,9,6], k = 4
Output:
[2,3,3,4]
Constraints
1 <= nums.length <= 105
0 <= nums[i] <= 109
1 <= k <= nums.length
Approach and Intuition
The key to solving this problem lies in understanding the concept of "most competitive subsequence". Essentially, for a subsequence to be competitive, it should be the smallest lexicographical sequence possible of the given length k
from the array. We can approach this problem using a greedy strategy and a stack to help maintain the required order of elements:
- Initialize an empty stack.
- Loop through each element in the array:
- While there is any element left in the stack AND the last element in the stack is greater than the current element from the array AND the stack size plus the remaining elements in the array is still greater than or equal to
k
, pop the stack. This step ensures that we always have the smallest possible value at the current position for our result. - Push the current element on the stack if the size of the stack is less than
k
.
- While there is any element left in the stack AND the last element in the stack is greater than the current element from the array AND the stack size plus the remaining elements in the array is still greater than or equal to
- The stack essentially represents the most competitive subsequence of length
k
.
This method leverages the stack’s LIFO mechanism to maintain the smallest possible values in sequence and ensures that larger numbers are only kept when absolutely necessary to reach the size k
.
Solutions
- C++
- Java
class Solution {
public:
vector<int> findCompetitiveNumbers(vector<int>& inputNumbers, int requiredLength) {
deque<int> decreasingSequence;
int elementsToRemove = inputNumbers.size() - requiredLength;
for (int index = 0; index < inputNumbers.size(); index++) {
while (!decreasingSequence.empty() && decreasingSequence.back() > inputNumbers[index] &&
elementsToRemove > 0) {
decreasingSequence.pop_back();
elementsToRemove--;
}
decreasingSequence.push_back(inputNumbers[index]);
}
vector<int> competitiveSubset;
for (int count = 0; count < requiredLength; count++) {
competitiveSubset.push_back(decreasingSequence.front());
decreasingSequence.pop_front();
}
return competitiveSubset;
}
};
The provided C++ code implements a function to find the most competitive subsequence from a given list of integers. Here's a breakdown of the solution:
- The function named
findCompetitiveNumbers
accepts a vector of integersinputNumbers
and an integerrequiredLength
, representing the desired length of the subsequence. - It utilizes a double-ended queue (
deque<int>
) nameddecreasingSequence
to maintain elements of a potential competitive subsequence in a decreasing order, ensuring the smallest possible numbers are included. - The main computation involves iterating over the
inputNumbers
. For each number:- If the last element in
decreasingSequence
is greater than the current number, and there are still elements that can be removed (elementsToRemove
is greater than 0), the back of the deque is popped. This step essentially keeps the deque minimal by retaining competitive elements. - The current number is then added to
decreasingSequence
.
- If the last element in
- After processing all input numbers, the top
requiredLength
elements ofdecreasingSequence
are transferred to a vector calledcompetitiveSubset
. This vector represents the most competitive subsequence and is returned as the result.
This approach ensures that the resultant subsequence is, lexicographically, the smallest possible subsequence of the required length. By effectively managing the deque and tracking the number of allowable removals, the solution remains efficient and direct.
class Solution {
public int[] smallestSubsequence(int[] data, int k) {
Deque<Integer> minStack = new ArrayDeque<Integer>();
int removeOperations = data.length - k;
for (int i = 0; i < data.length; i++) {
while (!minStack.isEmpty() && minStack.peekLast() > data[i] && removeOperations > 0) {
minStack.pollLast();
removeOperations--;
}
minStack.addLast(data[i]);
}
int[] output = new int[k];
for (int i = 0; i < k; i++) {
output[i] = minStack.pollFirst();
}
return output;
}
}
The Java program provided is designed to find the most competitive subsequence of a given length k
from an array data
. The algorithm optimizes the sequence such that it is the lexicographically smallest possible subsequence of the specified length. The core data structure used in this implementation is a deque (Deque<Integer>
) which helps in efficiently managing the elements during the selection of the subsequence.
Here's a breakdown of how the code works:
- A deque (
minStack
) is used to keep potential candidates of the smallest subsequence. - The variable
removeOperations
calculates how many elements can be removed to attain a subsequence of lengthk
. - A loop iterates through each element of the array
data
.- Inside the loop, there's a nested while loop which checks if the last element in the
minStack
can be removed (i.e., if it's greater than the current element indata
and there are still allowable remove operations). This ensures that the sequence in the deque remains the smallest lexicographically. - The current element from
data
is then added tominStack
.
- Inside the loop, there's a nested while loop which checks if the last element in the
- After processing all elements in
data
, the firstk
elements ofminStack
are transferred to the output arrayoutput
. - The
output
array, containing the smallest lexicographical subsequence of lengthk
, is then returned.
In summary, this solution is effective in computing the desired subsequence due to its utilization of a deque which facilitates the maintenance of order while allowing for necessary removals, ensuring the resulting subsequence is the smallest possible. This method is both time-efficient and straightforward, leveraging simple iteration and condition checking to build the solution.
No comments yet.