Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
Given an integer array nums and a positive integer k, return the most competitive subsequence of nums of size k.
An array's subsequence is a resulting sequence obtained by erasing some (possibly zero) elements from the array.
We define that a subsequence a is more competitive than a subsequence b (of the same length) if in the first position where a and b differ, subsequence a has a number less than the corresponding number in b. For example, [1,3,4] is more competitive than [1,3,5] because the first position they differ is at the final number, and 4 is less than 5.
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 <= 1050 <= nums[i] <= 1091 <= k <= nums.lengthProblem summary: Given an integer array nums and a positive integer k, return the most competitive subsequence of nums of size k. An array's subsequence is a resulting sequence obtained by erasing some (possibly zero) elements from the array. We define that a subsequence a is more competitive than a subsequence b (of the same length) if in the first position where a and b differ, subsequence a has a number less than the corresponding number in b. For example, [1,3,4] is more competitive than [1,3,5] because the first position they differ is at the final number, and 4 is less than 5.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Stack · Greedy
[3,5,2,6] 2
[2,4,3,3,5,4,9,6] 4
remove-k-digits)smallest-subsequence-of-distinct-characters)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1673: Find the Most Competitive Subsequence
class Solution {
public int[] mostCompetitive(int[] nums, int k) {
Deque<Integer> stk = new ArrayDeque<>();
int n = nums.length;
for (int i = 0; i < nums.length; ++i) {
while (!stk.isEmpty() && stk.peek() > nums[i] && stk.size() + n - i > k) {
stk.pop();
}
if (stk.size() < k) {
stk.push(nums[i]);
}
}
int[] ans = new int[stk.size()];
for (int i = ans.length - 1; i >= 0; --i) {
ans[i] = stk.pop();
}
return ans;
}
}
// Accepted solution for LeetCode #1673: Find the Most Competitive Subsequence
func mostCompetitive(nums []int, k int) []int {
stk := []int{}
n := len(nums)
for i, v := range nums {
for len(stk) > 0 && stk[len(stk)-1] > v && len(stk)+n-i > k {
stk = stk[:len(stk)-1]
}
if len(stk) < k {
stk = append(stk, v)
}
}
return stk
}
# Accepted solution for LeetCode #1673: Find the Most Competitive Subsequence
class Solution:
def mostCompetitive(self, nums: List[int], k: int) -> List[int]:
stk = []
n = len(nums)
for i, v in enumerate(nums):
while stk and stk[-1] > v and len(stk) + n - i > k:
stk.pop()
if len(stk) < k:
stk.append(v)
return stk
// Accepted solution for LeetCode #1673: Find the Most Competitive Subsequence
struct Solution;
impl Solution {
fn most_competitive(nums: Vec<i32>, k: i32) -> Vec<i32> {
let n = nums.len();
let k = k as usize;
let mut arr = vec![];
let mut m = 0;
for i in 0..n {
while let Some(&top) = arr.last() {
if top > nums[i] && k < n - m {
m += 1;
arr.pop();
} else {
break;
}
}
arr.push(nums[i]);
}
arr[0..k].to_vec()
}
}
#[test]
fn test() {
let nums = vec![3, 5, 2, 6];
let k = 2;
let res = vec![2, 6];
assert_eq!(Solution::most_competitive(nums, k), res);
let nums = vec![2, 4, 3, 3, 5, 4, 9, 6];
let k = 4;
let res = vec![2, 3, 3, 4];
assert_eq!(Solution::most_competitive(nums, k), res);
}
// Accepted solution for LeetCode #1673: Find the Most Competitive Subsequence
function mostCompetitive(nums: number[], k: number): number[] {
const stk: number[] = [];
const n = nums.length;
for (let i = 0; i < n; ++i) {
while (stk.length && stk.at(-1)! > nums[i] && stk.length + n - i > k) {
stk.pop();
}
if (stk.length < k) {
stk.push(nums[i]);
}
}
return stk;
}
Use this to step through a reusable interview workflow for this problem.
For each element, scan left (or right) to find the next greater/smaller element. The inner scan can visit up to n elements per outer iteration, giving O(n²) total comparisons. No extra space needed beyond loop variables.
Each element is pushed onto the stack at most once and popped at most once, giving 2n total operations = O(n). The stack itself holds at most n elements in the worst case. The key insight: amortized O(1) per element despite the inner while-loop.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: Pushing without popping stale elements invalidates next-greater/next-smaller logic.
Usually fails on: Indices point to blocked elements and outputs shift.
Fix: Pop while invariant is violated before pushing current element.
Wrong move: Locally optimal choices may fail globally.
Usually fails on: Counterexamples appear on crafted input orderings.
Fix: Verify with exchange argument or monotonic objective before committing.