class Solution:
def pancakeSort(self, arr):
res = []
n = len(arr)
for size in range(n, 1, -1):
# Find index of the max element in arr[0:size]
max_idx = arr.index(max(arr[0:size]))
if max_idx == size - 1:
continue # Already in place
# Flip max element to front if not already there
if max_idx != 0:
res.append(max_idx + 1)
arr[:max_idx + 1] = reversed(arr[:max_idx + 1])
# Flip it to its final position
res.append(size)
arr[:size] = reversed(arr[:size])
return res
class Solution {
public:
vector<int> pancakeSort(vector<int>& arr) {
vector<int> res;
int n = arr.size();
for (int size = n; size > 1; --size) {
int max_idx = max_element(arr.begin(), arr.begin() + size) - arr.begin();
if (max_idx == size - 1) continue;
if (max_idx != 0) {
res.push_back(max_idx + 1);
reverse(arr.begin(), arr.begin() + max_idx + 1);
}
res.push_back(size);
reverse(arr.begin(), arr.begin() + size);
}
return res;
}
};
class Solution {
public List<Integer> pancakeSort(int[] arr) {
List<Integer> res = new ArrayList<>();
int n = arr.length;
for (int size = n; size > 1; size--) {
int maxIdx = 0;
for (int i = 0; i < size; i++) {
if (arr[i] > arr[maxIdx]) maxIdx = i;
}
if (maxIdx == size - 1) continue;
if (maxIdx != 0) {
res.add(maxIdx + 1);
reverse(arr, 0, maxIdx);
}
res.add(size);
reverse(arr, 0, size - 1);
}
return res;
}
private void reverse(int[] arr, int l, int r) {
while (l < r) {
int tmp = arr[l];
arr[l++] = arr[r];
arr[r--] = tmp;
}
}
}
var pancakeSort = function(arr) {
const res = [];
for (let size = arr.length; size > 1; size--) {
let maxIdx = 0;
for (let i = 0; i < size; i++) {
if (arr[i] > arr[maxIdx]) maxIdx = i;
}
if (maxIdx === size - 1) continue;
if (maxIdx !== 0) {
res.push(maxIdx + 1);
reverse(arr, 0, maxIdx);
}
res.push(size);
reverse(arr, 0, size - 1);
}
return res;
};
function reverse(arr, l, r) {
while (l < r) {
[arr[l], arr[r]] = [arr[r], arr[l]];
l++; r--;
}
}
The Pancake Sorting problem asks you to sort an array arr
containing distinct integers from 1 to n
using a special operation called a "pancake flip". In one pancake flip, you choose an integer k
(where 1 <= k <= n
) and reverse the order of the first k
elements of arr
. The goal is to return a list of k
values representing the sequence of flips that sorts the array in ascending order.
k
.arr
contains all integers from 1 to n
exactly once.At first glance, the problem might seem similar to traditional sorting, but the restriction to only flip prefixes adds a unique twist. A brute-force approach could try all possible flip sequences, but that quickly becomes infeasible for larger arrays. Instead, we need a strategy that leverages the properties of the flip operation:
The key insight is to repeatedly place the largest unsorted element at its correct position by first flipping it to the front (if it isn't already there), then flipping it into place at the end of the current unsorted section. This mimics how you might sort pancakes by size using a spatula in real life!
The solution follows a step-by-step greedy strategy:
n
down to 2, find the index of the largest unsorted element (which should be size
).
size
so the largest element moves to its final position at the end of the current unsorted section.
We use simple array operations for flipping and keep track of the flips performed. This approach ensures that after each iteration, the largest remaining unsorted element is placed correctly, and the rest of the array is untouched.
Let's walk through an example with arr = [3, 2, 4, 1]
:
Each step moves the largest unsorted element to its correct position, using at most two flips per element.
Brute-force approach: Would try all possible flip sequences, leading to exponential time complexity (much worse than O(n!)), which is not feasible.
Optimized approach:
The algorithm is efficient enough for the problem's constraints.
Pancake Sorting is an intriguing variation of sorting where only prefix reversals are allowed. By approaching the problem greedily—always placing the largest unsorted element in its correct spot using at most two flips—we achieve a simple yet effective solution. This method is both intuitive and efficient, reflecting the elegance of transforming a real-world analogy into an algorithmic strategy.