Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
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 ?
- l tracks the length of remaining elements to consider
- r represents how many more elements we need to select
- For each position, we find the minimum element using the complement operator (~)
- 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.
