1+ """
2+ =========================================================
3+ LeetCode 143. Reorder List
4+ =========================================================
5+
6+ Problem:
7+ Reorder a singly linked list from:
8+
9+ L0 → L1 → L2 → ... → Ln
10+
11+ to
12+
13+ L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → ...
14+
15+ The list must be modified in-place without changing node values.
16+
17+ ---------------------------------------------------------
18+ Approach 1 : Stack + Queue (pop() + pop(0))
19+ ---------------------------------------------------------
20+
21+ Idea:
22+ 1. Store every node in a list.
23+ 2. Keep the first node as the head.
24+ 3. Alternate between:
25+ - Taking the last node (pop())
26+ - Taking the first remaining node (pop(0))
27+ 4. Connect them one after another.
28+
29+ Example:
30+
31+ Original:
32+ 1 → 2 → 3 → 4 → 5
33+
34+ Stored:
35+ [1,2,3,4,5]
36+
37+ After removing first node:
38+ [2,3,4,5]
39+
40+ Connect:
41+
42+ 1 → 5
43+ 5 → 2
44+ 2 → 4
45+ 4 → 3
46+
47+ Result:
48+
49+ 1 → 5 → 2 → 4 → 3
50+
51+ Time Complexity:
52+ O(n²)
53+ Reason:
54+ pop() -> O(1)
55+ pop(0) -> O(n)
56+ pop(0) is executed nearly n/2 times.
57+
58+ Space Complexity:
59+ O(n)
60+
61+ =========================================================
62+ """
63+
64+ # Definition for singly-linked list.
65+ # class ListNode:
66+ # def __init__(self, val=0, next=None):
67+ # self.val = val
68+ # self.next = next
69+
70+ from typing import Optional
71+
72+
73+ class SolutionStackQueue :
74+ def reorderList (self , head : Optional [ListNode ]) -> None :
75+ if not head or not head .next :
76+ return
77+
78+ nodes = []
79+
80+ curr = head
81+ while curr :
82+ nodes .append (curr )
83+ curr = curr .next
84+
85+ curr = head
86+ nodes .pop (0 )
87+
88+ while nodes :
89+ curr .next = nodes .pop ()
90+ curr = curr .next
91+
92+ if nodes :
93+ curr .next = nodes .pop (0 )
94+ curr = curr .next
95+
96+ curr .next = None
97+
98+
99+ """
100+ =========================================================
101+ Approach 2 : Array + Two Pointers
102+ (Optimal Brute Force)
103+ =========================================================
104+
105+ Idea:
106+ 1. Store every node inside an array.
107+ 2. Remove the first node because head is already fixed.
108+ 3. Use two pointers:
109+ i -> first remaining node
110+ j -> last remaining node
111+ 4. Alternate between:
112+ nodes[j]
113+ nodes[i]
114+
115+ Example:
116+
117+ Original:
118+
119+ 1 → 2 → 3 → 4 → 5
120+
121+ Array:
122+
123+ [2,3,4,5]
124+
125+ i = 0
126+ j = 3
127+
128+ Connect:
129+
130+ 1 → 5
131+ 5 → 2
132+ 2 → 4
133+ 4 → 3
134+
135+ Result:
136+
137+ 1 → 5 → 2 → 4 → 3
138+
139+ Time Complexity:
140+ O(n)
141+
142+ Reason:
143+ Every node is visited only once.
144+
145+ Space Complexity:
146+ O(n)
147+
148+ =========================================================
149+ """
150+
151+
152+ class SolutionArray :
153+ def reorderList (self , head : Optional [ListNode ]) -> None :
154+ if not head or not head .next :
155+ return
156+
157+ nodes = []
158+
159+ curr = head
160+ while curr :
161+ nodes .append (curr )
162+ curr = curr .next
163+
164+ curr = head
165+ nodes .pop (0 )
166+
167+ i = 0
168+ j = len (nodes ) - 1
169+
170+ while i <= j :
171+ curr .next = nodes [j ]
172+ curr = curr .next
173+ j -= 1
174+
175+ if i <= j :
176+ curr .next = nodes [i ]
177+ curr = curr .next
178+ i += 1
179+
180+ curr .next = None
181+
182+
183+ """
184+ =========================================================
185+ Approach 3 : Optimal (Find Middle + Reverse + Merge)
186+ =========================================================
187+
188+ Idea:
189+
190+ Step 1:
191+ Find the middle using Slow & Fast pointers.
192+
193+ Example:
194+
195+ 1 → 2 → 3 → 4 → 5
196+ ↑
197+ slow
198+
199+ ---------------------------------------------------------
200+
201+ Step 2:
202+ Reverse the second half.
203+
204+ Before:
205+
206+ 4 → 5
207+
208+ After:
209+
210+ 5 → 4
211+
212+ Now we have
213+
214+ First Half:
215+ 1 → 2 → 3
216+
217+ Second Half:
218+ 5 → 4
219+
220+ ---------------------------------------------------------
221+
222+ Step 3:
223+ Merge both halves alternately.
224+
225+ 1 → 5
226+ ↓
227+
228+ 2 → 4
229+ ↓
230+
231+ 3
232+
233+ Final:
234+
235+ 1 → 5 → 2 → 4 → 3
236+
237+ ---------------------------------------------------------
238+
239+ Dry Run
240+
241+ Input:
242+
243+ 1 → 2 → 3 → 4 → 5
244+
245+ Find Middle
246+
247+ First Half:
248+ 1 → 2 → 3
249+
250+ Second Half:
251+ 4 → 5
252+
253+ Reverse
254+
255+ 5 → 4
256+
257+ Merge
258+
259+ Iteration 1
260+
261+ 1 → 5 → 2
262+
263+ Iteration 2
264+
265+ 2 → 4 → 3
266+
267+ Final
268+
269+ 1 → 5 → 2 → 4 → 3
270+
271+ ---------------------------------------------------------
272+
273+ Time Complexity:
274+ O(n)
275+
276+ Reason:
277+ Find middle -> O(n)
278+ Reverse -> O(n)
279+ Merge -> O(n)
280+
281+ Total:
282+ O(n)
283+
284+ Space Complexity:
285+ O(1)
286+
287+ This is the expected interview solution.
288+
289+ =========================================================
290+ """
291+
292+
293+ class SolutionOptimal :
294+ def reorderList (self , head : Optional [ListNode ]) -> None :
295+ if not head or not head .next :
296+ return
297+
298+ # -------------------------------------------------
299+ # Step 1: Find Middle
300+ # -------------------------------------------------
301+ slow = head
302+ fast = head
303+
304+ while fast and fast .next :
305+ slow = slow .next
306+ fast = fast .next .next
307+
308+ # -------------------------------------------------
309+ # Step 2: Reverse Second Half
310+ # -------------------------------------------------
311+ prev = None
312+ curr = slow .next
313+ slow .next = None
314+
315+ while curr :
316+ nxt = curr .next
317+ curr .next = prev
318+ prev = curr
319+ curr = nxt
320+
321+ # -------------------------------------------------
322+ # Step 3: Merge Two Halves
323+ # -------------------------------------------------
324+ first = head
325+ second = prev
326+
327+ while second :
328+ temp1 = first .next
329+ temp2 = second .next
330+
331+ first .next = second
332+ second .next = temp1
333+
334+ first = temp1
335+ second = temp2
0 commit comments