Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

439. Ternary Expression Parser - Leetcode Solution

Code Implementation

class Solution:
    def parseTernary(self, expression: str) -> str:
        stack = []
        n = len(expression)
        i = n - 1
        while i >= 0:
            c = expression[i]
            if c == '?':
                true_expr = stack.pop()
                stack.pop()  # Remove ':'
                false_expr = stack.pop()
                i -= 1
                cond = expression[i]
                if cond == 'T':
                    stack.append(true_expr)
                else:
                    stack.append(false_expr)
            elif c != ':':
                stack.append(c)
            i -= 1
        return stack[-1]
      
class Solution {
public:
    string parseTernary(string expression) {
        stack<char> st;
        int n = expression.size();
        for (int i = n - 1; i >= 0; --i) {
            char c = expression[i];
            if (c == '?') {
                char trueExpr = st.top(); st.pop();
                st.pop(); // remove ':'
                char falseExpr = st.top(); st.pop();
                --i;
                if (expression[i] == 'T') {
                    st.push(trueExpr);
                } else {
                    st.push(falseExpr);
                }
            } else if (c != ':') {
                st.push(c);
            }
        }
        return string(1, st.top());
    }
};
      
class Solution {
    public String parseTernary(String expression) {
        Stack<Character> stack = new Stack<>();
        int n = expression.length();
        for (int i = n - 1; i >= 0; --i) {
            char c = expression.charAt(i);
            if (c == '?') {
                char trueExpr = stack.pop();
                stack.pop(); // remove ':'
                char falseExpr = stack.pop();
                i--;
                char cond = expression.charAt(i);
                if (cond == 'T') {
                    stack.push(trueExpr);
                } else {
                    stack.push(falseExpr);
                }
            } else if (c != ':') {
                stack.push(c);
            }
        }
        return stack.peek() + "";
    }
}
      
var parseTernary = function(expression) {
    let stack = [];
    let n = expression.length;
    let i = n - 1;
    while (i >= 0) {
        let c = expression[i];
        if (c === '?') {
            let trueExpr = stack.pop();
            stack.pop(); // remove ':'
            let falseExpr = stack.pop();
            i--;
            let cond = expression[i];
            stack.push(cond === 'T' ? trueExpr : falseExpr);
        } else if (c !== ':') {
            stack.push(c);
        }
        i--;
    }
    return stack[stack.length - 1];
};
      

Problem Description

You are given a string expression representing a nested ternary expression. The ternary expression uses the format condition ? exprTrue : exprFalse, where condition is always either 'T' (true) or 'F' (false), and exprTrue and exprFalse can themselves be either a single character or another ternary expression.

Your task is to evaluate the expression and return the result as a single character string. You can assume the expression is always valid and properly nested. There is exactly one valid solution for each input, and you do not need to reuse any elements from the expression.

For example, given expression = "T?2:3", the output should be "2". For expression = "F?1:T?4:5", the output should be "4".

Thought Process

At first glance, parsing a ternary expression may seem complex due to its nested nature. A brute-force approach might involve recursively parsing the string, identifying the matching ? and : for each condition, and evaluating each subexpression. However, this can get tricky and inefficient as the nesting increases.

By observing that ternary expressions are evaluated from right to left (right associativity), we can simplify the process. Instead of searching for matching symbols or using recursion, we can process the string backwards and use a stack to keep track of intermediate results. This shift from recursion to using a stack (iterative approach) allows us to efficiently and cleanly handle nested expressions without complex string manipulation.

Solution Approach

The optimal strategy is to process the expression from the end to the beginning, using a stack to handle subexpressions. Here's how we can break down the approach:

  1. Initialize a stack: The stack will store characters and intermediate results as we process the expression backwards.
  2. Iterate from right to left: For each character in the expression, do the following:
    • If the character is not a ? or :, push it onto the stack.
    • If the character is a ?, pop the top two results (which correspond to the true and false expressions), then check the condition just before the ?. Push the result of the ternary operation back onto the stack.
    • If the character is a :, skip it (it only serves as a separator).
  3. Repeat until the entire expression is processed: At the end, the stack will contain the final result.

This method works efficiently because the stack always contains the next immediate result to be used in the ternary operation, and processing from right to left respects the right-associativity of ternary operators.

Example Walkthrough

Let's walk through the example expression = "F?1:T?4:5" step by step:

  1. Start from the right: stack is empty.
  2. Push '5' onto the stack.
  3. Push ':' (skip in logic, but for clarity, it's encountered).
  4. Push '4' onto the stack.
  5. Push '?'.
  6. Push 'T' onto the stack.
  7. Push ':' (skip).
  8. Push '1' onto the stack.
  9. Push '?'.
  10. Push 'F' onto the stack.
  11. When processing '?', pop '1' and 'T', and check the condition 'F':
    • Since 'F', select the false branch, which is the result of evaluating 'T?4:5'.
    • Process 'T?4:5': since 'T', select '4'.
    • So, the final result is '4'.

Thus, the answer is '4'.

Time and Space Complexity

Brute-force approach: Recursively parsing and evaluating each subexpression may result in O(N^2) time complexity in the worst case, due to repeated substring operations and recursive calls.

Optimized stack approach: Each character is processed exactly once, and each operation on the stack is O(1). Thus, the overall time complexity is O(N), where N is the length of the expression. The space complexity is also O(N) in the worst case, due to the stack storing up to N/2 elements for deeply nested expressions.

Summary

The key insight for solving the Ternary Expression Parser problem is recognizing the right-associativity of ternary expressions and leveraging a stack to iteratively evaluate the expression from right to left. This approach avoids recursion and complex string manipulation, leading to a clean, efficient, and elegant O(N) solution. By processing each character once and using a stack to manage intermediate results, we can handle any valid ternary expression, no matter how deeply nested.