1324. Print Words Vertically
Problem Description
You are given a string s
containing words separated by spaces. The task is to return these words arranged vertically (column by column) while maintaining their original order.
Each word should be placed in its own column, reading from top to bottom. When words have different lengths, shorter words should be padded with spaces to align with longer words. However, trailing spaces at the end of each row must be removed.
For example, if s = "HOW ARE YOU"
, the words would be arranged as:
H A Y
O R O
W E U
This would return ["HAY", "ORO", "WEU"]
as the result.
The solution works by:
- Splitting the input string into individual words
- Finding the maximum word length to determine how many rows are needed
- For each row position (0 to max length - 1):
- Extracting the character at that position from each word
- Using a space if the word is shorter than the current position
- Removing trailing spaces from the end of each row
- Adding the resulting string to the answer list
The key challenge is handling words of different lengths and ensuring no trailing spaces remain in the output strings.
Intuition
The key insight is to visualize the problem as a matrix transformation. When we look at the words horizontally in the original string, we need to rotate our perspective by 90 degrees to read them vertically.
Think of placing each word in a row of a 2D grid. The word "HOW" goes in row 0, "ARE" in row 1, and "YOU" in row 2. Now, instead of reading row by row, we need to read column by column.
This naturally leads us to iterate through column indices rather than word indices. For each column position j
, we collect the j-th
character from every word. This is similar to transposing a matrix where we swap rows and columns.
The challenge comes from words having different lengths. In a regular matrix, all rows have the same length, but here we need to handle the irregularity. When a word is too short for the current column position, we pad it with a space character. This ensures all columns align properly.
The final piece of the puzzle is handling trailing spaces. Since we're building strings column by column and some words might be shorter than others, we might end up with spaces at the end of our constructed strings. The problem specifically forbids trailing spaces, so we need to trim them. This is why we pop spaces from the end of each constructed column string before adding it to our result.
The approach essentially treats the problem as reading a jagged 2D array column-wise, where we pad shorter rows with spaces but clean up any trailing spaces in the final output.
Solution Approach
The implementation follows a straightforward approach to construct vertical strings from the input:
-
Split the input string into words: Using
s.split()
, we separate the input string into individual words and store them in a list. -
Find the maximum word length: We use
max(len(w) for w in words)
to determine the longest word. This valuen
tells us how many vertical strings (rows) we need to create, as we'll need to iterate through character positions from 0 ton-1
. -
Build each vertical string column by column: We iterate through each character position
j
from 0 ton-1
:- For each position
j
, we create a temporary listt
that collects thej-th
character from each word - We use a list comprehension:
[w[j] if j < len(w) else ' ' for w in words]
- This checks if the current word
w
has a character at positionj
. If yes, we takew[j]
; otherwise, we use a space' '
as padding
- For each position
-
Remove trailing spaces: After collecting all characters for position
j
, we have a listt
that might have trailing spaces (from shorter words). We remove these trailing spaces using a while loop:while t[-1] == ' ': t.pop()
This repeatedly removes the last element if it's a space, ensuring no trailing spaces remain.
-
Convert list to string and add to result: Once trailing spaces are removed, we join the characters in list
t
into a single string using''.join(t)
and append it to our answer list. -
Return the result: After processing all character positions, we return the
ans
list containing all vertical strings.
The time complexity is O(m * n)
where m
is the number of words and n
is the length of the longest word, as we need to process each character position for each word. The space complexity is also O(m * n)
for storing the result.
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 a small example with s = "TO BE OR NOT TO BE"
.
Step 1: Split into words
words = ["TO", "BE", "OR", "NOT", "TO", "BE"]
Step 2: Find maximum word length
max_length = 3 (from "NOT")
This means we'll need to create 3 vertical strings (one for each character position 0, 1, and 2).
Step 3: Build vertical strings column by column
For position j = 0
(first character of each word):
- "TO"[0] = 'T'
- "BE"[0] = 'B'
- "OR"[0] = 'O'
- "NOT"[0] = 'N'
- "TO"[0] = 'T'
- "BE"[0] = 'B'
- List
t = ['T', 'B', 'O', 'N', 'T', 'B']
- No trailing spaces to remove
- Result:
"TBONTB"
For position j = 1
(second character of each word):
- "TO"[1] = 'O'
- "BE"[1] = 'E'
- "OR"[1] = 'R'
- "NOT"[1] = 'O'
- "TO"[1] = 'O'
- "BE"[1] = 'E'
- List
t = ['O', 'E', 'R', 'O', 'O', 'E']
- No trailing spaces to remove
- Result:
"OEROOE"
For position j = 2
(third character of each word):
- "TO" has length 2, so use ' ' (space)
- "BE" has length 2, so use ' ' (space)
- "OR" has length 2, so use ' ' (space)
- "NOT"[2] = 'T'
- "TO" has length 2, so use ' ' (space)
- "BE" has length 2, so use ' ' (space)
- List
t = [' ', ' ', ' ', 'T', ' ', ' ']
- Remove trailing spaces:
[' ', ' ', ' ', 'T']
- Result:
" T"
(3 spaces followed by 'T')
Step 4: Return result
ans = ["TBONTB", "OEROOE", " T"]
The words are now arranged vertically:
T B O N T B
O E R O O E
T
Reading column by column gives us our answer.
Solution Implementation
1class Solution:
2 def printVertically(self, s: str) -> List[str]:
3 # Split the input string into individual words
4 words = s.split()
5
6 # Find the maximum length among all words
7 max_length = max(len(word) for word in words)
8
9 # Initialize result list to store vertical strings
10 result = []
11
12 # Iterate through each column position (0 to max_length-1)
13 for col_index in range(max_length):
14 # Build current column by extracting character at col_index from each word
15 # If word is shorter than col_index, use space as placeholder
16 current_column = []
17 for word in words:
18 if col_index < len(word):
19 current_column.append(word[col_index])
20 else:
21 current_column.append(' ')
22
23 # Remove trailing spaces from the current column
24 while current_column and current_column[-1] == ' ':
25 current_column.pop()
26
27 # Join characters to form the vertical string and add to result
28 result.append(''.join(current_column))
29
30 return result
31
1class Solution {
2 public List<String> printVertically(String s) {
3 // Split the input string into individual words
4 String[] words = s.split(" ");
5
6 // Find the maximum length among all words
7 int maxLength = 0;
8 for (String word : words) {
9 maxLength = Math.max(maxLength, word.length());
10 }
11
12 // Initialize the result list to store vertical strings
13 List<String> result = new ArrayList<>();
14
15 // Iterate through each character position (column index)
16 for (int columnIndex = 0; columnIndex < maxLength; columnIndex++) {
17 StringBuilder verticalString = new StringBuilder();
18
19 // Build the vertical string by taking character at current position from each word
20 for (String word : words) {
21 if (columnIndex < word.length()) {
22 // If the word has a character at this position, append it
23 verticalString.append(word.charAt(columnIndex));
24 } else {
25 // If the word is shorter, append a space for padding
26 verticalString.append(' ');
27 }
28 }
29
30 // Remove trailing spaces from the vertical string
31 while (verticalString.length() > 0 &&
32 verticalString.charAt(verticalString.length() - 1) == ' ') {
33 verticalString.deleteCharAt(verticalString.length() - 1);
34 }
35
36 // Add the processed vertical string to the result
37 result.add(verticalString.toString());
38 }
39
40 return result;
41 }
42}
43
1class Solution {
2public:
3 vector<string> printVertically(string s) {
4 // Parse the input string into individual words
5 stringstream ss(s);
6 vector<string> words;
7 string word;
8 int maxLength = 0;
9
10 // Extract words from the string and find the maximum word length
11 while (ss >> word) {
12 words.emplace_back(word);
13 maxLength = max(maxLength, static_cast<int>(word.size()));
14 }
15
16 vector<string> result;
17
18 // Build vertical strings column by column
19 for (int colIndex = 0; colIndex < maxLength; ++colIndex) {
20 string verticalString;
21
22 // For each word, append the character at current column index
23 // If the word is shorter than current column index, append a space
24 for (const auto& currentWord : words) {
25 if (colIndex < currentWord.size()) {
26 verticalString += currentWord[colIndex];
27 } else {
28 verticalString += ' ';
29 }
30 }
31
32 // Remove trailing spaces from the vertical string
33 while (!verticalString.empty() && verticalString.back() == ' ') {
34 verticalString.pop_back();
35 }
36
37 result.emplace_back(verticalString);
38 }
39
40 return result;
41 }
42};
43
1function printVertically(s: string): string[] {
2 // Parse the input string into individual words
3 const words: string[] = s.split(' ').filter(word => word.length > 0);
4
5 // Find the maximum word length
6 let maxLength: number = 0;
7 for (const word of words) {
8 maxLength = Math.max(maxLength, word.length);
9 }
10
11 const result: string[] = [];
12
13 // Build vertical strings column by column
14 for (let colIndex = 0; colIndex < maxLength; colIndex++) {
15 let verticalString: string = '';
16
17 // For each word, append the character at current column index
18 // If the word is shorter than current column index, append a space
19 for (const currentWord of words) {
20 if (colIndex < currentWord.length) {
21 verticalString += currentWord[colIndex];
22 } else {
23 verticalString += ' ';
24 }
25 }
26
27 // Remove trailing spaces from the vertical string
28 while (verticalString.length > 0 && verticalString[verticalString.length - 1] === ' ') {
29 verticalString = verticalString.slice(0, -1);
30 }
31
32 result.push(verticalString);
33 }
34
35 return result;
36}
37
Time and Space Complexity
Time Complexity: O(m * n)
- Splitting the string takes
O(m)
wherem
is the total length of the input string - Finding the maximum word length takes
O(k)
wherek
is the number of words - The main loop runs
n
times wheren
is the length of the longest word - Inside each iteration:
- List comprehension creates a list of size
k
inO(k)
time - The while loop for removing trailing spaces runs at most
k
times (worst case) - Joining the characters takes
O(k)
time
- List comprehension creates a list of size
- Overall:
O(m) + O(k) + O(n * k) = O(m * n)
sincem ≥ n
andm ≥ k
Space Complexity: O(m * n)
- The
words
list stores all words, takingO(m)
space wherem
is the total length of input - The temporary list
t
in each iteration takesO(k)
space wherek
is the number of words - The answer list
ans
storesn
strings, and in the worst case, each string can have up tok
characters - Total space for output:
O(n * k)
- Overall:
O(m) + O(n * k) = O(m * n)
since the output dominates andm ≥ k
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Forgetting to Remove Trailing Spaces
One of the most common mistakes is forgetting to remove trailing spaces from each vertical string. The problem explicitly requires that trailing spaces be removed, but leading and internal spaces must be preserved.
Incorrect approach:
# This would include trailing spaces in the result
current_column = []
for word in words:
if col_index < len(word):
current_column.append(word[col_index])
else:
current_column.append(' ')
result.append(''.join(current_column)) # Directly adding without trimming
Correct approach:
# Remove trailing spaces before adding to result while current_column and current_column[-1] == ' ': current_column.pop() result.append(''.join(current_column))
2. Using String Concatenation Instead of List
Building strings through repeated concatenation is inefficient in Python. Some might try to build each vertical string character by character using string concatenation.
Inefficient approach:
vertical_string = ""
for word in words:
if col_index < len(word):
vertical_string += word[col_index]
else:
vertical_string += ' '
# Then trim trailing spaces from the string
Better approach: Use a list to collect characters first, then join them. Lists are mutable and more efficient for building strings piece by piece.
3. Incorrectly Handling Empty Input or Edge Cases
The code might fail if the input string is empty or contains only spaces.
Potential issue:
words = s.split()
max_length = max(len(word) for word in words) # Fails if words is empty
Solution:
words = s.split()
if not words: # Handle empty input
return []
max_length = max(len(word) for word in words)
4. Off-by-One Errors in Index Checking
A subtle mistake is using <=
instead of <
when checking if a word has a character at a given position.
Incorrect:
if col_index <= len(word): # This would cause IndexError
current_column.append(word[col_index])
Correct:
if col_index < len(word): # Proper bounds checking
current_column.append(word[col_index])
5. Not Preserving Internal Spaces
Some might mistakenly try to remove all spaces, not just trailing ones. Remember that spaces between words (internal spaces) must be preserved.
Wrong:
# This would incorrectly remove all spaces current_column = [c for c in current_column if c != ' ']
Right: Only remove trailing spaces while preserving internal ones by popping from the end until a non-space character is found.
What are the most two important steps in writing a depth first search function? (Select 2)
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!