easyStackPattern: Monotonic Stack
Longest Decreasing Subsequence Length Solution
Problem Statement
Given an array of integers `values`, find the length of the longest subsequence such that each element is strictly less than the element preceding it in the subsequence.
Examples
Example 1:
Input:[5, 3, 4, 2, 1]
Output:2
Explanation: The longest decreasing subsequence is [5, 3, 2, 1] or [5, 4, 2, 1], both of length 4.
Example 2:
Input:[10, 9, 2, 5, 3, 7, 101, 18]
Output:4
Explanation: The longest decreasing subsequence is [10, 9, 5, 3] or [10, 9, 2] or [10, 5, 3]. The maximum length is 4.
Example 3:
Input:[1, 1, 1, 1]
Output:1
Explanation: Since elements must be strictly decreasing, the longest subsequence has length 1 (any single element).
Constraints
- 1 <= values.length <= 2500
- -10^9 <= values[i] <= 10^9
- All elements in `values` are integers.
Time: O(n log n) Space: O(n)
This problem can be solved using dynamic programming in O(n^2) time. A more optimized O(n log n) solution involves maintaining an auxiliary array that stores the smallest tail of all decreasing subsequences of a given length. Binary search is used to efficiently update this array.
Run, Test & Submit Code
Ready to practice this challenge? Launch our interactive compilation environment with compiler validation.
Solve on Interactive WorkspaceTested Solutions
def longest_decreasing_subsequence_length(values):
if not values:
return 0
tails = [] # stores the smallest tail of all decreasing subsequences of length i+1
for value in values:
# Find the first element in tails that is strictly smaller than value
# Using binary search for efficiency
low = 0
high = len(tails)
while low < high:
mid = (low + high) // 2
if tails[mid] >= value: # We want to find the smallest tail < value, so if tails[mid] >= value, we search right
low = mid + 1
else: # tails[mid] < value, this is a potential candidate
high = mid
# After the loop, 'low' is the index of the first element in tails that is < value
if low == len(tails):
tails.append(value) # If no element is < value, extend the longest subsequence
else:
tails[low] = value # Otherwise, replace the smallest tail that is < value
return len(tails)