Python 1324.py
class Solution:
def printVertically(self, s: str) -> List[str]:
words = s.split()
longest = 0
for w in words:
longest = max(longest, len(w))
result = [ "" ] * longest
for w in words:
w += " " * (longest - len(w)) # all words will have same size
for i, c in enumerate(w):
result[i] += c
for r in result:
yield r.rstrip()
Difficulty
and has an acceptance rate of about 67% (70k+ submissions).
Typical patterns to solve this problem:
- Array
- Simulation
- String
AI Disclaimer
However, two years later I set up this website and used various AI tools to generate most of the walkthrough / explanations below.
See this dedicated page for more details.
Code Walkthrough
Overview
The provided Solution class implements a method that receives a single string containing one or more words separated by spaces and produces a vertical representation of those words. Each column of the output corresponds to a character position within the longest word, and rows are built by reading characters from the same index across all words. The method yields each resulting row after removing any trailing blanks.
Key Steps
Splitting the Input
words = s.split()
The input string s is divided into a list of individual words using the default whitespace delimiter. This step automatically discards any leading, trailing, or multiple consecutive spaces, ensuring that the subsequent processing works with clean tokens.
Determining the Maximum Word Length
longest = 0
for w in words:
longest = max(longest, len(w))
A linear scan computes the length of the longest word. By maintaining a single integer variable, the algorithm avoids constructing auxiliary collections, which keeps memory usage minimal.
Preparing the Result Container
result = [ "" ] * longest
A list of empty strings is pre-allocated with a size equal to the longest word. Each element of this list will accumulate characters for one vertical column. Pre-allocation eliminates the need for dynamic list growth during the main construction loop.
Normalizing Word Lengths
w += " " * (longest - len(w)) # all words will have same size
Each word is padded on the right with spaces so that its length matches longest. This uniform length guarantees that the inner character-by-character loop can safely iterate over every index without additional boundary checks.
Building the Vertical Strings
for i, c in enumerate(w):
result[i] += c
For the padded word, the loop iterates over each character together with its index. The character c is appended to the corresponding entry in result. Because result was pre-allocated, each concatenation extends an existing string rather than inserting new list elements.
Trimming and Yielding Output
for r in result:
yield r.rstrip()
After all words have contributed their characters, each accumulated string may contain trailing spaces that originated from the padding of shorter words. The rstrip() call removes those trailing blanks, and the method yields the cleaned rows one by one, making the function a generator.
Edge Cases Handled
When the input consists of a single word, the longest word length equals that word’s length, and the padding step adds zero spaces. The inner loop still processes each character, and the final rstrip() has no effect, yielding the original word as the sole vertical line.
If the input string is empty or contains only whitespace, s.split() returns an empty list. The subsequent loop that determines longest never executes, leaving longest at its initial value of zero. Consequently, result becomes an empty list, and the final for r in result loop yields nothing, which correctly represents the absence of vertical output.
Words of varying lengths are normalized by the padding step, ensuring that shorter words contribute spaces for missing positions. The final rstrip() removes those spaces only at the end of each line, preserving internal spaces that represent actual characters from longer words.
Performance Optimizations Observed
The algorithm avoids creating intermediate data structures beyond the essential words list and the result list. The longest word length is computed with a simple accumulator rather than a more expensive built-in max on a generated list, reducing temporary memory allocation.
Padding each word uses string multiplication (" " * n), which is a fast, low-overhead operation in Python. By performing padding once per word, the inner character loop can operate without conditional checks for index bounds, leading to a tight inner loop that only performs character concatenation.
Pre-allocating the result list with the exact required size eliminates the need for dynamic resizing during the construction phase. This fixed-size allocation contributes to predictable memory usage and avoids the overhead associated with list growth.
Finally, the use of a generator (yield) allows the caller to consume rows lazily, which can be advantageous when only a subset of the vertical output is needed, as it prevents the construction of an entire list of strings in memory.
ELI5 - Simplified Explanation
Imagine you have a handful of alphabet blocks and you want to stack them into towers. The words in the sentence act like rows of blocks. First, the code looks at all the words to see which one is the tallest tower needed. Once it knows how tall the biggest tower is, it makes sure every word is padded out with invisible spaces so they are all the same length.
After that, it picks up the first letter from every word and builds the first tower. Then it picks up all the second letters to build the next tower, and it keeps doing this until every letter has a spot in a tower. Finally, it takes a look at those towers and cleans up any extra empty spaces hanging off the ends, showing each tower one by one.
Code Quality
Complexity Analysis
Other Solutions
Obviously, I did that after I solved the problem myself.
In general, AlgoMonster and WalkCCC solutions are high-quality and always worth a look.
I haven't checked most of the other solutions, but they might be helpful as well.
And of course, the LeetCode forum is always a good place (or even the best) to look for alternative approaches.
(click on a column header to sort the table)
| author | ||||||||
|---|---|---|---|---|---|---|---|---|
| author | solutions | |||||||
| www | AlgoMonster | C++ | Java | Python | TS | |||
| WalkCCC | C++ | Java | Python | |||||
| leetcode.ca | C++ | Java | Python | Go | ||||
| Progiez | C++ | Java | Python | |||||
| github | black-shadows | C++ | ||||||
| charles-wangkai | Java | |||||||
| everthis | JS | |||||||
| fpdjsns | C++ | |||||||
| fsq | C++ | |||||||
| JoshCrozier | JS | |||||||
| lkwq007 | Python | |||||||
| lzl124631x | C++ | |||||||
| suxrobGM | C# | |||||||
| varunu28 | Java | |||||||
| AlgoMonster | C++, Python, Java, TypeScript | |||||||
| WalkCCC | C++, Python, Java | |||||||
| leetcode.ca | C++, Go, Java, Python | |||||||
| Progiez | C++, Java, Python | |||||||
| black-shadows | C++, C++ | |||||||
| charles-wangkai | Java | |||||||
| everthis | JavaScript | |||||||
| fpdjsns | C++ | |||||||
| fsq | C++ | |||||||
| JoshCrozier | JavaScript | |||||||
| lkwq007 | Python | |||||||
| lzl124631x | C++ | |||||||
| suxrobGM | C# | |||||||
| varunu28 | Java |
Videos
Solved On The Same Day
- problem 680: Valid Palindrome II
- problem 478: Generate Random Point in a Circle
- problem 497: Random Point in Non-overlapping Rectangles
- problem 519: Random Flip Matrix
- problem 581: Shortest Unsorted Continuous Subarray
- problem 659: Split Array into Consecutive Subsequences
- problem 738: Monotone Increasing Digits
- problem 743: Network Delay Time
- problem 769: Max Chunks To Make Sorted
- problem 985: Sum of Even Numbers After Queries
- problem 1048: Longest String Chain
- problem 1094: Car Pooling
- problem 1680: Concatenation of Consecutive Binary Numbers
- problem 1823: Find the Winner of the Circular Game
- problem 1860: Incremental Memory Leak
- problem 1922: Count Good Numbers
- problem 2487: Remove Nodes From Linked List
- problem 381: Insert Delete GetRandom O(1) - Duplicates allowed
- problem 517: Super Washing Machines
- problem 632: Smallest Range Covering Elements from K Lists
Extra
- Tech Stack - my development environment and tools
- AI - how AI helped me create this website (NOT solving the problems)
- Progress - progression over time
- Quality - code quality