Quick Overview

Given a permutation of 1 to n and a window size, sort exactly one contiguous window of that size into ascending order so that the resulting array is lexicographically as large as possible. It tests careful reasoning about lexicographic comparison, a mandatory operation that may leave the array unchanged, and efficiency on inputs of up to 200,000 elements.

Lexicographically Largest Permutation After Sorting One Fixed-Length Window

Company: Amazon

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Online Assessment

A logistics team processes shipments in a fixed order before dispatch. The order is given as `shipment_order`, a permutation of the integers `1` to `n`, and you are also given an integer `window_size`. You must perform the following operation exactly once: choose a contiguous window of exactly `window_size` positions and rearrange the values inside it into ascending order, leaving every other position unchanged. Return the lexicographically largest array that can result from this operation. ### Function Signature ```python def maximize_shipment_order(shipment_order: list[int], window_size: int) -> list[int]: ``` ### Rules - Positions are 0-indexed. A window starting at index `i` covers indices `i` through `i + window_size - 1`, so `0 <= i <= n - window_size`. - The operation is mandatory and is applied exactly once. Choosing a window that is already in ascending order is allowed; it leaves the array unchanged. - An array `A` is lexicographically larger than an array `B` of the same length if, at the first index where they differ, `A` has the larger value. - Several windows may produce the same best array. The answer is that array, which is unique. - Return the full resulting array of length `n`. ### Constraints - `1 <= window_size <= n <= 2 * 10^5`, where `n = len(shipment_order)` - `shipment_order` is a permutation of `1, 2, ..., n`, so `1 <= shipment_order[i] <= n` and all values are distinct. ### Examples **Example 1** ```text Input: shipment_order = [5, 1, 4, 3, 2], window_size = 3 Output: [5, 1, 3, 4, 2] ``` Sorting the window that starts at index 0 gives `[1, 4, 5, 3, 2]`, at index 1 gives `[5, 1, 3, 4, 2]`, and at index 2 gives `[5, 1, 2, 3, 4]`. The largest of the three is `[5, 1, 3, 4, 2]`. **Example 2** ```text Input: shipment_order = [1, 2, 3, 5, 4], window_size = 2 Output: [1, 2, 3, 5, 4] ``` The windows starting at indices 0, 1 and 2 are already sorted and leave the array unchanged. Sorting the window at index 3 gives `[1, 2, 3, 4, 5]`, which is smaller, so choosing an already sorted window is optimal. **Example 3** ```text Input: shipment_order = [3, 1, 2], window_size = 3 Output: [1, 2, 3] ``` The only window is the whole array, so the operation must sort it.

Overview: Given a permutation of 1 to n and a window size, sort exactly one contiguous window of that size into ascending order so that the resulting array is lexicographically as large as possible. It tests careful reasoning about lexicographic comparison, a mandatory operation that may leave the array unchanged, and efficiency on inputs of up to 200,000 elements.

Read the full Amazon Software Engineer interview experience this question came from

A logistics team processes shipments in a fixed order before dispatch. You are given `shipment_order`, a permutation of the integers `1` to `n`, and an integer `window_size`. You must perform the following operation exactly once: choose a contiguous window of exactly `window_size` positions and rearrange the values inside it into ascending order, leaving every other position unchanged. Return the lexicographically largest array that can result from this operation. **Rules** - Positions are 0-indexed. A window starting at index `i` covers indices `i` through `i + window_size - 1`, so `0 <= i <= n - window_size`. - The operation is mandatory and is applied exactly once. Choosing a window whose values are already in ascending order is allowed; it leaves the array unchanged. - An array `A` is lexicographically larger than an array `B` of the same length if, at the first index where they differ, `A` has the larger value. - Several windows may produce the same best array. The answer is that array, which is unique. - Return the full resulting array of length `n`. **Constraints** - `1 <= window_size <= n <= 2 * 10^5`, where `n = len(shipment_order)` - `shipment_order` is a permutation of `1, 2, ..., n`, so `1 <= shipment_order[i] <= n` and all values are distinct. No input or output value exceeds `2 * 10^5`, so every value fits in a 32-bit signed integer. **Example 1** ``` Input: shipment_order = [5, 1, 4, 3, 2], window_size = 3 Output: [5, 1, 3, 4, 2] ``` Sorting the window that starts at index 0 gives `[1, 4, 5, 3, 2]`, at index 1 gives `[5, 1, 3, 4, 2]`, and at index 2 gives `[5, 1, 2, 3, 4]`. The largest of the three is `[5, 1, 3, 4, 2]`. **Example 2** ``` Input: shipment_order = [1, 2, 3, 5, 4], window_size = 2 Output: [1, 2, 3, 5, 4] ``` The windows starting at indices 0, 1 and 2 are already sorted and leave the array unchanged. Sorting the window at index 3 gives `[1, 2, 3, 4, 5]`, which is smaller, so choosing an already sorted window is optimal.

Constraints

  • 1 <= window_size <= n <= 2 * 10^5, where n = len(shipment_order)
  • shipment_order is a permutation of 1, 2, ..., n, so 1 <= shipment_order[i] <= n and all values are distinct

Examples

Input: ([1], 1)

Expected Output: [1]

Explanation: Minimum valid input: n = 1 and window_size = 1; the only window is already sorted.

Input: ([2, 1], 2)

Expected Output: [1, 2]

Explanation: window_size = n = 2: the single window must be sorted.

Hints

  1. Compare an array with the result of sorting one of its windows. Can sorting a window ever make the array lexicographically larger? What does that say when some window is already in ascending order (Example 2)?
  2. For a window that does change the array, look at the first index where the result differs from the original. How does that index decide which of two windows gives the larger array?
  3. When two windows first change the array at the same index, compare how much of the array after that index each one rearranges (Example 1).

Loading coding console...

Show the approach

Approach

Key fact: sorting a window into ascending order never makes the array lexicographically larger. At the first window position whose value differs from the sorted order, the sorted window places the minimum of the values from that position to the window end, which is strictly smaller than the value that was there. So if any window is already ascending, the unchanged array is the answer (Example 2). Otherwise every choice lowers the array, and window i is judged by change(i), the first index where its result differs from the original. A larger change(i) wins outright: the other result is already smaller at the earlier index, where this one still matches the original. Among windows with the same change position p, the earliest start wins. For window i, positions i..p-1 already hold the smallest window values in order, so sorting window i is the same as sorting the range p..i+k-1. A later window sorts the longer range p..i'+k-1, which equals sorting the shorter range first and then the longer one, and that second sort can only lower the array or leave it equal (Example 1).

Computing change(i): let next_smaller[j] be the first index after j holding a smaller value (n if none), found with one monotonic-stack pass. With e = i + k - 1, position j of the window is in place, given every earlier window position is, exactly when no smaller value follows it inside the window, that is next_smaller[j] > e. Hence change(i) is the smallest j >= i with next_smaller[j] <= e, and the window is already sorted when no such j exists. Sweep j from n - 1 down to 0 with a candidate stack whose top is the smallest index. Before pushing j, pop every candidate whose next_smaller is at least next_smaller[j]: whenever such a candidate would qualify, j qualifies too and is smaller. When j is a legal start (j <= n - k), pop candidates with next_smaller > e: the threshold only shrinks as the start moves left, so they never qualify again. The smallest qualifying index is never popped by either rule, so after these pops the top is change(j); an empty stack means window j is already sorted and the original array is returned. Keep the largest change, letting the later-visited (smaller) start win ties, then sort that one window.

Edge cases: n = 1; window_size = 1 (every window is trivially sorted, so the array is unchanged); window_size = n (one window, the result is fully sorted); a fully ascending array (unchanged); a strictly descending array (the last legal start wins); and a sorted window that exists only at the last legal start.

Time complexity:
O(n + k log k), where k = window_size
Space complexity:
O(n)