Reverse Segments
The Problem
Given an array and a list of segment boundaries [l, r], reverse the elements within each segment in-place. Elements outside the segments are untouched.
Input: arr = [1, 2, 3, 4, 5, 6, 7, 8], segments = [(0, 3), (4, 7)]
Output: arr = [4, 3, 2, 1, 8, 7, 6, 5]
↑ ↑ ↑ ↑
segment 0 reversed segment 1 reversed
Examples
Example 1 — two segments
Input: arr = [1, 2, 3, 4, 5, 6, 7, 8], segments = [(0, 3), (4, 7)]
Output: [4, 3, 2, 1, 8, 7, 6, 5]
Example 2 — single segment in the middle
Input: arr = [1, 2, 3, 4, 5], segments = [(1, 3)]
Output: [1, 4, 3, 2, 5]
Example 3 — entire array as one segment
Input: arr = [1, 2, 3, 4, 5], segments = [(0, 4)]
Output: [5, 4, 3, 2, 1]
Example 4 — single-element segment
Input: arr = [1, 2, 3], segments = [(1, 1)]
Output: [1, 2, 3] (reversing one element is a no-op)
Intuition
You already have the exact tool for this: the two-pointer reversal from “Flip Characters”. Reversing a segment [l, r] is identical to reversing the whole array — just start left = l and right = r instead of 0 and n-1.
For multiple segments, simply apply the two-pointer reversal once per segment. Each reversal is independent — the segments don’t overlap, so the order you process them in doesn’t matter.
---
config:
theme: base
themeVariables:
primaryColor: "#dbeafe"
primaryBorderColor: "#3b82f6"
primaryTextColor: "#1e3a5f"
lineColor: "#64748b"
secondaryColor: "#ede9fe"
tertiaryColor: "#fef9c3"
---
flowchart TB
subgraph ORIG["Original: [1, 2, 3, 4, 5, 6, 7, 8]"]
direction LR
A["1"] --- B["2"] --- C["3"] --- D["4"] --- E["5"] --- F["6"] --- G["7"] --- H["8"]
end
subgraph SEG0["Reverse segment (0,3): left=0, right=3"]
direction LR
A1(["left=0"]) --> D1["4"] --- C1["3"] --- B1["2"] --- A2["1"] --- E1["5"] --- F1["6"] --- G1["7"] --- H1["8"]
A2 --> D2(["right=3 done"])
end
subgraph SEG1["Reverse segment (4,7): left=4, right=7"]
direction LR
A3["4"] --- B3["3"] --- C3["2"] --- D3["1"] --- E3(["left=4"]) --> H3["8"] --- G3["7"] --- F3["6"] --- E4["5"]
E4 --> H4(["right=7 done"])
end
subgraph FINAL["Result: [4, 3, 2, 1, 8, 7, 6, 5]"]
direction LR
R0["4"] --- R1["3"] --- R2["2"] --- R3["1"] --- R4["8"] --- R5["7"] --- R6["6"] --- R7["5"]
end
ORIG -->|"apply two-pointer reversal on [0,3]"| SEG0
SEG0 -->|"apply two-pointer reversal on [4,7]"| SEG1
SEG1 --> FINAL
Reversing two segments of [1,2,3,4,5,6,7,8] — each segment is reversed independently using the standard two-pointer swap-and-converge.
Applying the Diagnostic Questions
| Check | Answer for Reverse Segments |
|---|---|
| ✅ Two positions simultaneously? | Yes — arr[left] and arr[right] are swapped together at each step within each segment |
| ✅ One near start, one near end? | Yes — for each segment (l, r), left = l, right = r |
| ✅ Both move inward? | Yes — left++, right-- within each segment’s reversal |
| ✅ Simple work at each step? | Yes — one swap per iteration |
Reverse Segments is structurally identical to Flip Characters — the only difference is that left and right start from a given (l, r) pair instead of (0, n-1). The two-pointer pattern is unchanged; the input just parameterises the range.
Why is this still “direct application” and not something more complex? No transformation of the data is needed — the segment boundaries are given directly, and the reversal within each boundary is the same swap-and-converge loop. There’s no searching for the right range, no sorting, no condition-based pointer movement. Two pointers enter a segment, march toward each other, and exit. The only outer logic is iterating through the list of segments.
What makes each segment’s reversal independent? Non-overlapping segments modify distinct array regions — each reverse_segment(arr, l, r) call touches only indices l through r. Because no two calls share an index, processing order is irrelevant: process segment 0 first or last, the result is the same. This independence is what allows the outer loop to be a simple for l, r in segments — no coordination between iterations needed.
Approach
- For each
(l, r)segment in thesegmentslist:- Set
left = l,right = r - While
left < right: swaparr[left]andarr[right],left++,right--
- Set
- Done — all segments reversed in-place
Solution
from typing import List, Tuple
class Solution:
def reverse_segment(self, arr: List[int], l: int, r: int) -> None:
"""Reverse arr[l..r] in-place using two pointers."""
left, right = l, r
while left < right:
arr[left], arr[right] = arr[right], arr[left]
left += 1
right -= 1
def reverse_segments(
self,
arr: List[int],
segments: List[Tuple[int, int]]
) -> None:
"""Reverse each segment in-place."""
for l, r in segments:
self.reverse_segment(arr, l, r)
# --- Test ---
sol = Solution()
a1 = [1, 2, 3, 4, 5, 6, 7, 8]
sol.reverse_segments(a1, [(0, 3), (4, 7)])
print(a1) # [4, 3, 2, 1, 8, 7, 6, 5]
a2 = [1, 2, 3, 4, 5]
sol.reverse_segments(a2, [(1, 3)])
print(a2) # [1, 4, 3, 2, 5]
a3 = [1, 2, 3, 4, 5]
sol.reverse_segments(a3, [(0, 4)])
print(a3) # [5, 4, 3, 2, 1]
a4 = [1, 2, 3]
sol.reverse_segments(a4, [(1, 1)])
print(a4) # [1, 2, 3]
Dry Run — Example 1
arr = [1, 2, 3, 4, 5, 6, 7, 8]
Segment (0, 3): left=0, right=3
| Step | left | right | Swap | Array |
|---|---|---|---|---|
| 1 | 0 | 3 | 1 ↔ 4 | [4, 2, 3, 1, 5, 6, 7, 8] |
| 2 | 1 | 2 | 2 ↔ 3 | [4, 3, 2, 1, 5, 6, 7, 8] |
| — | 2 | 1 | stop | — |
Segment (4, 7): left=4, right=7
| Step | left | right | Swap | Array |
|---|---|---|---|---|
| 1 | 4 | 7 | 5 ↔ 8 | [4, 3, 2, 1, 8, 6, 7, 5] |
| 2 | 5 | 6 | 6 ↔ 7 | [4, 3, 2, 1, 8, 7, 6, 5] |
| — | 6 | 5 | stop | — |
Result: [4, 3, 2, 1, 8, 7, 6, 5] ✓
Complexity Analysis
Let n = array length, k = number of segments, s = total elements covered by all segments.
| Complexity | Reasoning | |
|---|---|---|
| Time | O(s) | Each reversed element is visited once; O(n) in the worst case (all segments cover the full array) |
| Space | O(1) | Only pointer variables — in-place reversal |
Edge Cases
| Scenario | Segment | Effect |
|---|---|---|
| Single element | (i, i) | left = right — loop never runs, no-op |
| Entire array | (0, n-1) | Full reversal |
| Overlapping segments | (0,4), (2,6) | Undefined — this function assumes non-overlapping. Overlapping produces incorrect results. |
| Out-of-bounds | (-1, 5) | Caller’s responsibility to validate indices |
Key Takeaway
Reverse Segments shows that the two-pointer reversal is a reusable utility — not just a technique for one specific problem. By extracting it into reverse_segment(arr, l, r), you get a building block that can be called on any sub-range of any array. The next problem, Reverse Word Order, uses exactly this building block twice in sequence.