Facebook Pixel

1324. Print Words Vertically

MediumArrayStringSimulation
Leetcode Link

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:

  1. Splitting the input string into individual words
  2. Finding the maximum word length to determine how many rows are needed
  3. 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.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

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:

  1. Split the input string into words: Using s.split(), we separate the input string into individual words and store them in a list.

  2. Find the maximum word length: We use max(len(w) for w in words) to determine the longest word. This value n tells us how many vertical strings (rows) we need to create, as we'll need to iterate through character positions from 0 to n-1.

  3. Build each vertical string column by column: We iterate through each character position j from 0 to n-1:

    • For each position j, we create a temporary list t that collects the j-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 position j. If yes, we take w[j]; otherwise, we use a space ' ' as padding
  4. Remove trailing spaces: After collecting all characters for position j, we have a list t 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.

  5. 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.

  6. 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 Evaluator

Example 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) where m is the total length of the input string
  • Finding the maximum word length takes O(k) where k is the number of words
  • The main loop runs n times where n is the length of the longest word
  • Inside each iteration:
    • List comprehension creates a list of size k in O(k) time
    • The while loop for removing trailing spaces runs at most k times (worst case)
    • Joining the characters takes O(k) time
  • Overall: O(m) + O(k) + O(n * k) = O(m * n) since m ≥ n and m ≥ k

Space Complexity: O(m * n)

  • The words list stores all words, taking O(m) space where m is the total length of input
  • The temporary list t in each iteration takes O(k) space where k is the number of words
  • The answer list ans stores n strings, and in the worst case, each string can have up to k characters
  • Total space for output: O(n * k)
  • Overall: O(m) + O(n * k) = O(m * n) since the output dominates and m ≥ 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.

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

What are the most two important steps in writing a depth first search function? (Select 2)


Recommended Readings

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

Load More