Python 0969.py
class Solution:
def pancakeSort(self, arr: List[int]) -> List[int]:
for need in range(len(arr), 0, -1):
where = arr.index(need)
# already at correct position
if where == len(arr):
continue
# flip largest value to front
arr[:where + 1] = arr[:where + 1][::-1]
yield where + 1
# flip it to its final position and remove it
arr = arr[1:need][::-1]
yield need
Difficulty
and has an acceptance rate of about 0% (0k+ submissions).
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 implementation defines a Solution class with a pancakeSort method that produces a sequence of flip operations required to sort an input list of distinct integers using the pancake sorting technique. The method is written as a generator, yielding each flip size as it is determined, which allows the caller to consume the operations lazily.
Core Logic
The algorithm proceeds by iterating over the target values in descending order, from the largest element down to 1. For each target value (need), it first locates the current position of that value in the working list (where = arr.index(need)). If the element is already positioned at the end of the unsorted portion, the loop skips further work for that iteration.
When the element is not at its final location, two flips are performed:
-
Bring the target to the front - the slice up to and including
whereis reversed, moving the desired element to index 0. The size of this flip (where + 1) is yielded.arr[:where + 1] = arr[:where + 1][::-1] yield where + 1 -
Move the target to its final position - the prefix that now contains the target is reversed again, this time covering the whole unsorted prefix (
need). The slice operation also discards the element that has just been placed correctly, effectively shrinking the working list for the next iteration. The size of this second flip (need) is yielded.arr = arr[1:need][::-1] yield need
The loop continues until all values have been positioned, at which point the generator exhausts.
Edge-Case Handling
The code gracefully handles several boundary conditions without explicit branching:
-
Single-element input - The outer loop runs once with
need = 1. The index of1is0, the conditionwhere == len(arr)is false, so the element is flipped to the front (a no-op) and then the second flip reduces the list to an empty slice. The generator yields1twice, which is a valid sequence for a single element. -
Element already at its final spot - When
whereequals the length of the current working list, thecontinuestatement skips both flips, avoiding unnecessary work. -
Target already at the front - If
whereis0, the first slice reversal is a no-op but still yields1. The subsequent slicearr[1:need][::-1]correctly removes the front element and reverses the remaining prefix, preserving the algorithm’s invariant. -
Empty list - The range in the outer loop evaluates to an empty sequence, so the generator produces no output, which is appropriate for an already sorted (trivially empty) collection.
Performance Optimizations
Several choices in the implementation contribute to efficient execution:
-
In-place slice reversal - The first flip modifies the original list segment directly (
arr[:where + 1] = ...), avoiding the allocation of a new list for that operation. -
Progressive reduction of the working list - By reassigning
arrto a sliced and reversed sub-list (arr = arr[1:need][::-1]), the algorithm discards the portion that has already been sorted. This reduces the size of subsequentindexsearches and slice operations, leading to fewer element inspections as the loop advances. -
Generator pattern - Using
yieldstreams each flip size as soon as it is known, eliminating the need for an intermediate collection to store all results. This reduces memory pressure, especially for large inputs where the number of flips can be proportional to the list length. -
Direct use of
list.index- The built-inindexmethod is implemented in C and provides fast linear search for the target value, which is generally faster than a manual Python loop.
Overall, the method combines concise Pythonic constructs with careful in-place modifications and lazy output generation to achieve an effective pancake sorting routine.
ELI5 - Simplified Explanation
Imagine a stack of pancakes sitting on a plate. Some are big and some are small, but they are all mixed up. To make a neat stack, all the big ones should be at the bottom and the small ones should be at the top.
Because flipping the whole stack is the only way to move them, think of a giant spatula sliding under the pancakes to turn them over. The code looks for the biggest pancake that is still in the wrong spot and slides the spatula under it. By flipping them, that big pancake moves to the very top. Then, another flip moves it all the way down to the bottom where it belongs.
The code repeats this process over and over. It picks the next biggest pancake, moves it to the top, then sends it to its new home at the bottom. Each time a pancake finds its final spot, the pile gets a little bit smaller because that pancake is finished. Eventually, every pancake is sorted from smallest on top to biggest on the bottom, just like a perfect breakfast tower. Every time a flip happens, the code remembers the move.
Code Quality
Complexity Analysis
As a rule of thumb, the maximum input size for one second execution time is
- factorial: up to 10 elements
- exponential: up to 20 elements
- polynomial: a few thousand elements
- loglinear: up to 100,000 elements
- linear: a few million elements
- logarithmic: a billion elements
- constant: practically unlimited
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++ | Python | Java | TS | ||||
| WalkCCC | C++ | Python | Java | ||||||
| leetcode.ca | C++ | Python | Java | Rust | Go | TS | |||
| LeetcodeHelp | C++ | Python | Java | ||||||
| Progiez | C++ | Python | Java | ||||||
| github | aylei | Rust | |||||||
| BigEggStudy | C# | ||||||||
| black-shadows | C++ | ||||||||
| charles-wangkai | Java | ||||||||
| everthis | JS | ||||||||
| fpdjsns | C++ | ||||||||
| fsq | C++ | ||||||||
| halfrost | Go | ||||||||
| haoel | Python | ||||||||
| JoshCrozier | JS | ||||||||
| keineahnung2345 | C++ | ||||||||
| lkwq007 | Python | ||||||||
| MacJim | C++ | ||||||||
| suxrobGM | C# | ||||||||
| trung-hn | Python | ||||||||
| varunu28 | Java | ||||||||
| XiaotaoGuo | C++ | ||||||||
| YuriSpiridonov | Python | ||||||||
| AlgoMonster | C++, Python, Java, TypeScript | ||||||||
| WalkCCC | C++, Python, Java | ||||||||
| leetcode.ca | C++, Go, Java, Python, Rust, TypeScript | ||||||||
| LeetcodeHelp | C++, Java, Python | ||||||||
| Progiez | C++, Java, Python | ||||||||
| aylei | Rust | ||||||||
| BigEggStudy | C# | ||||||||
| black-shadows | C++, C++ | ||||||||
| charles-wangkai | Java | ||||||||
| everthis | JavaScript | ||||||||
| fpdjsns | C++ | ||||||||
| fsq | C++ | ||||||||
| halfrost | Go | ||||||||
| haoel | Python | ||||||||
| JoshCrozier | JavaScript | ||||||||
| keineahnung2345 | C++ | ||||||||
| lkwq007 | Python | ||||||||
| MacJim | C++ | ||||||||
| suxrobGM | C# | ||||||||
| trung-hn | Python | ||||||||
| varunu28 | Java | ||||||||
| XiaotaoGuo | C++ | ||||||||
| YuriSpiridonov | Python |
Videos
Solved On The Same Day
- problem 1217: Minimum Cost to Move Chips to The Same Position
- problem 1221: Split a String in Balanced Strings
- problem 1323: Maximum 69 Number
- problem 1710: Maximum Units on a Truck
- problem 991: Broken Calculator
- problem 1605: Find Valid Matrix Given Row and Column Sums
- problem 630: Course Schedule III
- problem 1425: Constrained Subsequence Sum
- problem 2147: Number of Ways to Divide a Long Corridor
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