AlgoMaster Logo

Increasing Triplet Subsequence

Last Updated: March 20, 2026

medium
4 min read

Understanding the Problem

We need to find three elements in the array that are strictly increasing and appear in left-to-right order. We don't need to find which three, just whether they exist.

The constraint on array size (up to 500,000) is a strong hint that O(n^2) or worse won't cut it. The follow-up explicitly asks for O(n) time and O(1) space.

The key question to ask yourself is: as we scan through the array, what's the minimum information we need to track to know if a valid triplet can be completed?

Key Constraints:

  • 1 <= nums.length <= 5 * 10^5 → Half a million elements means O(n^2) would be 2.5 * 10^11 operations, far too slow. We need O(n log n) or better, ideally O(n).
  • -2^31 <= nums[i] <= 2^31 - 1 → Full 32-bit integer range. We need to handle extreme values like Integer.MAX_VALUE and Integer.MIN_VALUE without overflow issues.
  • The follow-up asks for O(n) time and O(1) space → This pushes us toward a greedy single-pass approach rather than precomputed arrays or sorting.

Approach 1: Brute Force

Intuition

The most direct approach is to try every combination of three indices. Pick an i, then pick a j > i, then pick a k > j, and check if the values are strictly increasing.

This is what you'd naturally write if you just translated the problem statement into code.

Algorithm

  1. For each index i from 0 to n-3:
  2. For each index j from i+1 to n-2:
  3. If nums[j] > nums[i], for each index k from j+1 to n-1:
  4. If nums[k] > nums[j], return true
  5. If no triplet found, return false

Example Walkthrough

1Initialize: check all (i, j, k) triplet combinations
0
2
1
1
2
5
3
0
4
4
5
6
1/5

Code

With three nested loops, we're re-scanning overlapping ranges from scratch for every pair. What if we precomputed the minimum value to the left and maximum value to the right of each position, so each check became O(1)?

Approach 2: Prefix Min and Suffix Max

Intuition

Here's a useful observation: for any index j to be the middle element of a valid triplet, two things must be true:

  1. There's some smaller value to its left
  2. There's some larger value to its right

We don't care which specific elements those are, just that they exist.

So what if we precomputed, for every position, the smallest value to its left and the largest value to its right? Then for each j, we just check if leftMin[j] < nums[j] < rightMax[j].

Algorithm

  1. Build a leftMin array where leftMin[i] is the minimum value in nums[0..i]
  2. Build a rightMax array where rightMax[i] is the maximum value in nums[i..n-1]
  3. For each index j from 1 to n-2, check if leftMin[j-1] < nums[j] and nums[j] < rightMax[j+1]
  4. If any such j exists, return true. Otherwise, return false.

Example Walkthrough

1Start with nums = [2, 1, 5, 0, 4, 6]
0
2
1
1
2
5
3
0
4
4
5
6
1/5

Code

This approach achieves O(n) time but uses two auxiliary arrays of size n. Can we track the same information using just two variables instead of two arrays?

Approach 3: Greedy Two Variables (Optimal)

Intuition

Here's the clever idea: instead of precomputing arrays, we track just two values as we scan left to right:

  • first: the smallest value we've seen so far (candidate for nums[i])
  • second: the smallest value we've seen that is greater than some earlier value (candidate for nums[j])

For any new number nums[k], if it's greater than second, we've found our triplet, because second was set based on some earlier first value.

The tricky part that confuses people: when first gets updated to a new, smaller value, second might still hold a value that was set relative to the old first. Is that a problem?

No. Even though first now points to a different position, second still represents a valid second element of a pair. There was some element before second in the array that was smaller than second, and that relationship hasn't changed. So if anything comes along that's bigger than second, the triplet is valid.

Algorithm

  1. Initialize first and second to infinity (or Integer.MAX_VALUE)
  2. For each number in the array:
    • If the number is less than or equal to first, update first to this number
    • Else if the number is less than or equal to second, update second to this number
    • Else, we found a number greater than both first and second, return true
  3. If the loop ends without finding a triplet, return false

Example Walkthrough

1Initialize: first = INF, second = INF
0
2
1
1
2
5
3
0
4
4
5
6
1/7

Code