Facebook Pixel

2810. Faulty Keyboard

EasyStringSimulation
Leetcode Link

Problem Description

You have a faulty laptop keyboard with a special behavior: whenever you type the character 'i', it reverses all the text that has been written so far on the screen. All other characters work normally and get added to the end of the text.

Given a string s (0-indexed), you need to simulate typing each character of s one by one using this faulty keyboard and return the final string that appears on the laptop screen.

For example, if you type "string":

  • Type 's': screen shows "s"
  • Type 't': screen shows "st"
  • Type 'r': screen shows "str"
  • Type 'i': screen reverses to "rts"
  • Type 'n': screen shows "rtsn"
  • Type 'g': screen shows "rtsng"

The solution uses a list t to track the current text on screen. For each character in the input string:

  • If the character is 'i', reverse the entire list using slicing t[::-1]
  • Otherwise, append the character to the end of the list
  • Finally, join all characters in the list to form the resulting string
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The problem asks us to simulate a specific keyboard behavior, which naturally leads us to think about directly simulating the typing process step by step.

Since we need to process each character in order and maintain the current state of the text on screen, we need a data structure that can:

  1. Add characters to the end efficiently
  2. Be reversed when we encounter an 'i'

A list (dynamic array) is perfect for this because:

  • We can append characters to the end in O(1) time
  • Python's list slicing [::-1] provides a clean way to reverse the entire list

The key insight is that we don't need to overthink this problem - we can literally follow what the keyboard does: go through each character, and either append it or reverse everything if it's an 'i'. The simulation approach directly mirrors the problem statement, making it both intuitive and easy to implement.

Using a list instead of string concatenation is also more efficient since strings are immutable in Python. Building the result character by character in a list and then joining at the end avoids creating multiple intermediate string objects.

Solution Approach

The solution uses a simulation approach to mimic the faulty keyboard behavior. Here's how the implementation works:

Data Structure:

  • We use a list t to store the characters that appear on the screen. A list is chosen over string concatenation because strings are immutable in Python, and we need to efficiently modify our result.

Algorithm Steps:

  1. Initialize an empty list t = [] to represent the screen content.

  2. Iterate through each character c in the input string s:

    • If c == 'i': Reverse the entire list using Python's slicing notation t = t[::-1]. This creates a new list with all elements in reverse order.
    • Otherwise: Append the character to the end of the list using t.append(c).
  3. After processing all characters, join the list elements into a final string using "".join(t) and return it.

Time Complexity Analysis:

  • Each character is processed once in a loop of length n
  • Appending a character takes O(1) time
  • Reversing the list takes O(k) time where k is the current length of the list
  • In the worst case (multiple 'i' characters), the total time complexity is O(n²)

Space Complexity:

  • We use a list t that can grow up to size n in the worst case
  • The space complexity is O(n)

The beauty of this solution lies in its simplicity - it directly simulates what the problem describes without any complex optimizations or data structures.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through the solution with the input string "abid":

Initial State:

  • Input: s = "abid"
  • Screen (list t): []

Step 1: Process 'a'

  • Character is not 'i', so append it
  • t.append('a')
  • Screen: ['a']

Step 2: Process 'b'

  • Character is not 'i', so append it
  • t.append('b')
  • Screen: ['a', 'b']

Step 3: Process 'i'

  • Character is 'i', so reverse the entire list
  • t = t[::-1]
  • Screen: ['b', 'a']

Step 4: Process 'd'

  • Character is not 'i', so append it
  • t.append('d')
  • Screen: ['b', 'a', 'd']

Final Step: Join the list

  • "".join(t) produces "bad"
  • Return: "bad"

This example demonstrates how the 'i' character triggers a reversal of everything typed so far. The characters 'a' and 'b' were initially typed in order, but when 'i' was encountered, they got reversed to 'b', 'a'. Then 'd' was simply appended to the end, resulting in the final string "bad".

Solution Implementation

1class Solution:
2    def finalString(self, s: str) -> str:
3        """
4        Builds a final string by processing each character in the input string.
5        When 'i' is encountered, the current result is reversed.
6        Any other character is appended to the result.
7      
8        Args:
9            s: Input string to process
10          
11        Returns:
12            The final processed string
13        """
14        # Initialize an empty list to store characters (more efficient than string concatenation)
15        result = []
16      
17        # Process each character in the input string
18        for char in s:
19            if char == 'i':
20                # Reverse the current result when 'i' is encountered
21                result = result[::-1]
22            else:
23                # Append any other character to the result
24                result.append(char)
25      
26        # Convert the list of characters back to a string
27        return ''.join(result)
28
1class Solution {
2    /**
3     * Processes a string by appending non-'i' characters and reversing on 'i'.
4     * When encountering character 'i', reverses the current result string.
5     * When encountering any other character, appends it to the result.
6     * 
7     * @param s the input string to process
8     * @return the final processed string after all operations
9     */
10    public String finalString(String s) {
11        // Initialize StringBuilder to build the result string efficiently
12        StringBuilder result = new StringBuilder();
13      
14        // Iterate through each character in the input string
15        for (char currentChar : s.toCharArray()) {
16            if (currentChar == 'i') {
17                // If current character is 'i', reverse the accumulated string
18                result.reverse();
19            } else {
20                // Otherwise, append the character to the result
21                result.append(currentChar);
22            }
23        }
24      
25        // Convert StringBuilder to String and return
26        return result.toString();
27    }
28}
29
1class Solution {
2public:
3    string finalString(string s) {
4        string result;  // String to store the processed result
5      
6        // Iterate through each character in the input string
7        for (char currentChar : s) {
8            if (currentChar == 'i') {
9                // If the character is 'i', reverse the current result string
10                reverse(result.begin(), result.end());
11            } else {
12                // Otherwise, append the character to the result string
13                result.push_back(currentChar);
14            }
15        }
16      
17        // Return the final processed string
18        return result;
19    }
20};
21
1/**
2 * Processes a string by building a result where 'i' reverses the current string
3 * and other characters are appended to the end
4 * @param s - The input string to process
5 * @returns The final processed string
6 */
7function finalString(s: string): string {
8    // Array to store characters as we build the result
9    const resultArray: string[] = [];
10  
11    // Process each character in the input string
12    for (const character of s) {
13        if (character === 'i') {
14            // When we encounter 'i', reverse the current result
15            resultArray.reverse();
16        } else {
17            // For any other character, append it to the result
18            resultArray.push(character);
19        }
20    }
21  
22    // Join the array into a final string and return
23    return resultArray.join('');
24}
25

Time and Space Complexity

Time Complexity: O(n²)

The time complexity is dominated by the reversal operation t = t[::-1]. In Python, slicing creates a new list, which takes O(k) time where k is the current length of the list. In the worst case, if all characters are 'i', we perform n reversals. The cost of these reversals would be:

  • First reversal: O(0) (empty list)
  • Second reversal: O(1)
  • Third reversal: O(2)
  • ...
  • n-th reversal: O(n-1)

Total time: O(0 + 1 + 2 + ... + (n-1)) = O(n²/2) = O(n²)

Even in the average case with mixed characters, the reversals still contribute to quadratic time complexity since each reversal operation creates a new list with time proportional to the current list size.

Space Complexity: O(n)

The space complexity is O(n) because:

  • The list t stores at most n characters (excluding 'i' characters)
  • Each reversal operation t[::-1] creates a new temporary list of the same size as t, but this temporary space is released after assignment
  • The final "".join(t) creates a string of size at most n

Therefore, the maximum space used at any point is proportional to n.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Using String Concatenation Instead of List

One of the most common mistakes is using string concatenation directly instead of a list to build the result:

Incorrect Approach:

def finalString(self, s: str) -> str:
    result = ""
    for char in s:
        if char == 'i':
            result = result[::-1]  # Creates a new string every time
        else:
            result += char  # Creates a new string every time
    return result

Why it's problematic: Strings in Python are immutable, so every concatenation or reversal creates a new string object. This leads to unnecessary memory overhead and can significantly slow down the solution for large inputs.

Solution: Use a list to collect characters and join them at the end, as shown in the correct implementation.

2. Forgetting to Handle Empty String Input

While the provided solution handles empty strings correctly, developers might add unnecessary checks:

Over-complicated:

def finalString(self, s: str) -> str:
    if not s:  # Unnecessary check
        return ""
    result = []
    # ... rest of the code

Solution: The original implementation naturally handles empty strings - the loop simply won't execute, and ''.join([]) returns an empty string.

3. Modifying the List In-Place During Reversal

Some might try to use result.reverse() thinking it's more efficient:

Incorrect:

def finalString(self, s: str) -> str:
    result = []
    for char in s:
        if char == 'i':
            result.reverse()  # Modifies in-place, but same effect
        else:
            result.append(char)
    return ''.join(result)

Why it could be confusing: While this actually works and might even be slightly more memory efficient, using result[::-1] is more idiomatic in Python and clearly shows the intent. The in-place reversal might lead to confusion about whether we're creating a new list or modifying the existing one.

4. Misunderstanding the Problem - Including 'i' in the Result

A critical misreading would be to include the 'i' character in the result before reversing:

Wrong Interpretation:

def finalString(self, s: str) -> str:
    result = []
    for char in s:
        result.append(char)  # Adding 'i' to result
        if char == 'i':
            result = result[::-1]
    return ''.join(result)

Solution: Carefully read the problem - when 'i' is typed, it triggers a reversal but doesn't appear in the text itself. The 'i' acts as a command, not a character to be displayed.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

How does quick sort divide the problem into subproblems?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More