Increasing Triplet Subsequence
Problem
Given an integer array nums, return true if there exists a strictly increasing subsequence of length 3, and false otherwise.
- 1 ≤ nums.length ≤ 5 * 10⁵
- −2³¹ ≤ nums[i] ≤ 2³¹ - 1
Example
nums = [2, 1, 5, 0, 4, 6]trueThe algorithm maintains two variables representing the smallest and second smallest values found so far in an increasing order. Iterating through nums, it updates these variables greedily: first to 2, then updates to 1 since 1 < 2, then second to 5 since 5 > 1, then first to 0 since 0 < 1, then second to 4 since 4 > 0, and finally encounters 6 which is greater than second (4), confirming the existence of an increasing triplet subsequence (0, 4, 6). The function returns true immediately upon this discovery.
Approach
Straightforward Solution
A brute-force approach would check all triplets with three nested loops, resulting in O(n^3) time, which is infeasible for large inputs. A more efficient O(n^2) approach uses dynamic programming to track the length of the longest increasing subsequence ending at each index, but this is still too slow for large arrays.
Core Observation
To detect an increasing triplet subsequence, it suffices to track two increasing values in order. If a third value larger than both is found, the subsequence exists. This relies on the principle that any increasing subsequence of length 3 must have a first and second element smaller than the third.
Path to Optimal
The key insight is that only the smallest and second smallest values matter to detect a triplet. By greedily updating these two values while scanning the array once, the algorithm can confirm the existence of a triplet in O(n) time and O(1) space. This approach avoids the overhead of full subsequence tracking and leverages the minimal state needed to detect the pattern.
Optimal Approach
Initialize two variables, first and second, to infinity. Iterate through nums. For each number n, if n is less than or equal to first, update first to n. Else if n is less than or equal to second, update second to n. Otherwise, n is greater than both first and second, so return true immediately. If the loop ends without returning, return false. This guarantees O(n) time and O(1) space.
Time
O(n)
The algorithm performs a single pass through the array, updating two variables and performing constant-time comparisons per element.
Space
O(1)
Only two variables are maintained regardless of input size, resulting in constant auxiliary space.
Pattern Spotlight
Greedy Algorithms (State Compression for Subsequence Detection)
When searching for a fixed-length increasing subsequence, track the minimal candidates for each subsequence position greedily; updating these candidates ensures that the discovery of a larger element confirms the subsequence without full enumeration.
Solution
| 1 | class Solution: |
| 2 | def increasingTriplet(self, nums: List[int]) -> bool: |
| 3 | first = float('inf') |
| 4 | second = float('inf') |
| 5 | |
| 6 | for n in nums: |
| 7 | if n <= first: |
| 8 | first = n |
| 9 | elif n <= second: |
| 10 | second = n |
| 11 | else: |
| 12 | return True |
| 13 | |
| 14 | return False |
Step-by-Step Solution
Initialize First and Second Minimum Trackers
| 3 | first = float('inf') |
| 4 | second = float('inf') |
Objective
To set up two variables representing the smallest and second smallest values found so far in the array.
Key Insight
Initializing both variables to infinity ensures that any number in the array will update them appropriately. This setup creates a baseline for comparison that allows the algorithm to greedily track the minimal increasing pairs needed to detect a triplet subsequence.
Interview Quick-Check
Core Logic
Using two variables to track the smallest and second smallest values compresses the subsequence detection state into constant space.
Common Pitfalls & Bugs
Initializing these variables incorrectly (e.g., to zero or the first element) can cause missed subsequences or incorrect results.
Iterate Through Array and Update Trackers Greedily
| 6 | for n in nums: |
| 7 | if n <= first: |
| 8 | first = n |
| 9 | elif n <= second: |
| 10 | second = n |
| 11 | else: |
| 12 | return True |
Objective
To scan the array once, updating the smallest and second smallest values or returning true when a valid triplet is found.
Key Insight
The algorithm compares each number to the current smallest and second smallest. If the number is smaller or equal to the smallest, it updates the smallest. If it is larger than the smallest but smaller or equal to the second smallest, it updates the second smallest. If it is larger than both, it confirms the existence of an increasing triplet subsequence and returns true immediately. This greedy update ensures the minimal candidates are always tracked, enabling early detection without full subsequence reconstruction.
Interview Quick-Check
Core Logic
The greedy update rules ensure that the smallest and second smallest values represent the best candidates for the first two elements of an increasing triplet.
State & Boundaries
The loop terminates early upon finding a number larger than both trackers, guaranteeing O(n) time.
Common Pitfalls & Bugs
Failing to use '<=' in comparisons can cause incorrect updates and missed subsequences.
Return False if No Increasing Triplet Found
| 14 | return False |
Objective
To return false after completing the iteration if no increasing triplet subsequence exists.
Key Insight
If the loop completes without returning true, it means no element was found that is larger than both the smallest and second smallest tracked values, so no increasing triplet subsequence exists. Returning false correctly signals this outcome.
Interview Quick-Check
Core Logic
Returning false after the loop ensures the function only confirms existence when the triplet condition is met.
Line Analysis
This solution has 4 Critical lines interviewers watch for.
return True
Return True to signal that an increasing triplet subsequence has been found.
Once an increasing triplet is detected, the algorithm immediately terminates because the problem only asks whether such a subsequence exists.
first = n
Update 'first' to the current number.
This update is critical because it compresses the subsequence state to the minimal first element, enabling the greedy detection of the triplet without storing the entire subsequence.
second = n
Update 'second' to the current number.
This line is essential because it refines the second candidate, allowing the algorithm to track the minimal increasing pair and detect when a third larger element appears.
else:
Identify that the current number completes an increasing triplet.
Reaching this branch means the current number is greater than both 'first' and 'second', since the previous conditions failed. This confirms an increasing triplet subsequence has been discovered.
first = float('inf')
Initialize 'first' to positive infinity to represent the smallest candidate.
Setting 'first' to infinity ensures any number in the array will be smaller, allowing the algorithm to update it correctly as the smallest value seen so far.
second = float('inf')
Initialize 'second' to positive infinity to represent the second smallest candidate.
Similarly, 'second' starts at infinity so it can be updated to the smallest number greater than 'first', maintaining the minimal second element for the subsequence.
return False
Return false if no increasing triplet subsequence is found after full iteration.
If the loop completes without returning true, it means no valid triplet exists, so returning false correctly signals this outcome.
if n <= first:
Check if the current number is less than or equal to 'first'.
If true, this number becomes the new smallest candidate, ensuring 'first' always holds the minimal value encountered so far.
elif n <= second:
Check if the current number is less than or equal to 'second'.
If the number is larger than 'first' but smaller or equal to 'second', it becomes the new candidate for the second element in the subsequence, maintaining the minimal second value.
for n in nums:
Begin iterating through each number in the input array.
A single pass through the array is sufficient to detect the increasing triplet subsequence by updating the two trackers greedily.
Test Your Understanding
Why does tracking only two variables suffice to detect an increasing triplet subsequence?
Because any increasing triplet must have a first and second element smaller than the third, maintaining the smallest and second smallest candidates allows immediate detection when a third larger element appears, confirming the subsequence without tracking all elements.
Related Problems
Greedy pattern
Don't just read it. Drill it.
Reconstruct Increasing Triplet Subsequence from memory until it sticks. AlgoDrill blanks out key lines and makes you fill them back in, step by step.
Unlock the Increasing Triplet Subsequence drill