Problem

Given a permutation $(P_1, P_2, \ldots, P_n)$ of the numbers (1, 2, \ldots, n), determine whether it is possible to obtain this permutation using a stack. The permutation is valid if and only if there are no indices (i < j < k) such that (P_j < P_k < P_i).

Examples

Example 1:

Input: 3
Output: 5
Explanation: There are 5 valid permutations for 3 distinct characters, as given by the 3rd Catalan number (C_n).

Example 2:

Input: 4
Output: 14
Explanation: There are 14 valid permutations for 4 distinct characters, as given by the 4th Catalan number (C_n).

Solution

Method 1 - Using Stack

To validate if a permutation can be obtained from a stack, we need to check for the condition (i < j < k) such that (P_j < P_k < P_i). This specific condition indicates that the values violate the sequence of stack operations.

  1. A stack works on a last-in, first-out (LIFO) basis.
  2. As you push elements to get to (P_i), elements (P_j) and (P_k) must appear in the correct order to abide by the stack properties.
  3. The condition (P_j < P_k < P_i) violates the stack property as (P_j) should have been out before (P_k) if (P_k) is expected to come out before (P_i).

Approach

  1. Use a stack data structure to simulate the behavior of generating the permutation from the sequence.
  2. Traverse the permutation and use the stack to manage the smallest elements at any point.
  3. Ensure that no index triplet violates the given condition.

Code

Java
public class Solution {
    public boolean canObtainPermutation(int[] permutation) {
        Stack<Integer> stack = new Stack<>();
        int lowestPossibleValue = Integer.MAX_VALUE;
        
        for (int value : permutation) {
            if (value > lowestPossibleValue) {
                while (!stack.isEmpty() && stack.peek() < value) {
                    lowestPossibleValue = stack.pop();
                }
            }
            stack.push(value);
        }
        
        return true;
    }

    // Example usage
    public static void main(String[] args) {
        Solution solution = new Solution();
        System.out.println(solution.canObtainPermutation(new int[]{1, 2, 3}));  // Output: True
        System.out.println(solution.canObtainPermutation(new int[]{3, 1, 2}));  // Output: False
    }
}
Python
class Solution:
    def can_obtain_permutation(self, permutation):
        stack = []
        lowest_possible_value = float('inf')
        for value in permutation:
            if value > lowest_possible_value:
                while stack and stack[-1] < value:
                    lowest_possible_value = stack.pop()
            stack.append(value)
        
        return True

# Example usage
solution = Solution()
print(solution.can_obtain_permutation([1, 2, 3]))  # Output: True
print(solution.can_obtain_permutation([3, 1, 2]))  # Output: False

Complexity

  • ⏰ Time complexity:  O(n)—since we only traverse the permutation once.
  • 🧺 Space complexity:  O(n)—due to the usage of stack space depending on the input size.