2810. Faulty Keyboard
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 slicingt[::-1]
- Otherwise, append the character to the end of the list
- Finally, join all characters in the list to form the resulting string
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:
- Add characters to the end efficiently
- 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:
-
Initialize an empty list
t = []
to represent the screen content. -
Iterate through each character
c
in the input strings
:- If
c == 'i'
: Reverse the entire list using Python's slicing notationt = 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)
.
- If
-
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 sizen
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 EvaluatorExample 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 mostn
characters (excluding 'i' characters) - Each reversal operation
t[::-1]
creates a new temporary list of the same size ast
, but this temporary space is released after assignment - The final
"".join(t)
creates a string of size at mostn
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.
How does quick sort divide the problem into subproblems?
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!