Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

969. Pancake Sorting - Leetcode Solution

Code Implementation

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--;
    }
}
      

Problem Description

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.

  • Each flip must reverse the prefix of the array up to the chosen k.
  • You may return any valid sequence of flips that results in a sorted array.
  • You should not reuse elements or perform unnecessary flips.
  • Input array arr contains all integers from 1 to n exactly once.

Thought Process

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:

  • Flipping a prefix can move any element to the front of the array.
  • By flipping twice, you can move any element to its correct position at the end of the unsorted section.

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!

Solution Approach

The solution follows a step-by-step greedy strategy:

  1. Iterate from the largest value down to 2: For each size from n down to 2, find the index of the largest unsorted element (which should be size).
  2. Flip the largest element to the front (if necessary): If the largest element is not already at the front, flip the prefix up to its index so it becomes the first element.
  3. Flip it into its correct position: Now, flip the prefix up to size so the largest element moves to its final position at the end of the current unsorted section.
  4. Repeat for the next largest value: Each time, the sorted section grows from the end of the array towards the front.

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.

Example Walkthrough

Let's walk through an example with arr = [3, 2, 4, 1]:

  1. size = 4: Largest value is 4 at index 2.
    • Flip first 3 elements: [4, 2, 3, 1] (flip k=3)
    • Flip first 4 elements: [1, 3, 2, 4] (flip k=4)
  2. size = 3: Largest value is 3 at index 1.
    • Flip first 2 elements: [3, 1, 2, 4] (flip k=2)
    • Flip first 3 elements: [2, 1, 3, 4] (flip k=3)
  3. size = 2: Largest value is 2 at index 0.
    • Flip first 2 elements: [1, 2, 3, 4] (flip k=2)
  4. Now the array is sorted! The sequence of flips is [3, 4, 2, 3, 2].

Each step moves the largest unsorted element to its correct position, using at most two flips per element.

Time and Space Complexity

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:

  • Time Complexity: O(n2) — For each of n elements, we may need to scan up to n elements to find the maximum, and perform up to two flips (each O(n)).
  • Space Complexity: O(n) — For the result list of flips and possibly for in-place array manipulations.

The algorithm is efficient enough for the problem's constraints.

Summary

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.