Program to find lexicographically smallest subsequence of size k in Python

Given a list of numbers and a value k, we need to find the lexicographically smallest subsequence of size k. A subsequence maintains the relative order of elements from the original list.

Problem Understanding

For example, if we have nums = [2, 3, 1, 10, 3, 4] and k = 3, we need to select 3 numbers that form the smallest possible sequence when compared lexicographically. The answer would be [1, 3, 4].

Algorithm Approach

To solve this problem, we use a greedy approach ?

  • For each position in our result, find the smallest possible element
  • Ensure we have enough remaining elements to complete the subsequence
  • Use the bitwise complement operator (~) to work backwards through the array

Example Implementation

class Solution:
    def solve(self, nums, k):
        l, r = len(nums), k - 1
        out = []
        for j in range(k):
            mn = nums[~r]
            for i in range(r, l):
                if mn >= nums[~i]:
                    mn = nums[~i]
                    l = i
            r -= 1
            out.append(mn)
        return out

# Test the solution
ob = Solution()
nums = [2, 3, 1, 10, 3, 4]
k = 3
result = ob.solve(nums, k)
print("Input:", nums, "k =", k)
print("Output:", result)
Input: [2, 3, 1, 10, 3, 4] k = 3
Output: [1, 3, 4]

How the Algorithm Works

The algorithm works by iteratively selecting the smallest possible element for each position ?

  1. l tracks the length of remaining elements to consider
  2. r represents how many more elements we need to select
  3. For each position, we find the minimum element using the complement operator (~)
  4. We ensure enough elements remain to complete the subsequence

Alternative Approach

Here's a more intuitive implementation using a stack-based approach ?

def find_smallest_subsequence(nums, k):
    n = len(nums)
    to_remove = n - k
    stack = []
    
    for num in nums:
        while stack and stack[-1] > num and to_remove > 0:
            stack.pop()
            to_remove -= 1
        stack.append(num)
    
    # Remove remaining elements if needed
    while to_remove > 0:
        stack.pop()
        to_remove -= 1
    
    return stack[:k]

# Test the alternative approach
nums = [2, 3, 1, 10, 3, 4]
k = 3
result = find_smallest_subsequence(nums, k)
print("Alternative approach result:", result)
Alternative approach result: [1, 3, 4]

Comparison of Approaches

Approach Time Complexity Space Complexity Readability
Greedy with Complement O(k×n) O(k) Medium
Stack-based O(n) O(n) High

Conclusion

Both approaches solve the lexicographically smallest subsequence problem effectively. The stack-based approach is more intuitive and efficient with O(n) time complexity, while the greedy approach uses bitwise operations for a compact solution.

Updated on: 2026-03-25T13:32:50+05:30

394 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements