Skip to content

Commit cc651a4

Browse files
Leetcode 143
1 parent 2927d50 commit cc651a4

1 file changed

Lines changed: 335 additions & 0 deletions

File tree

Leetcode/Leetcode_143.py

Lines changed: 335 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
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

Comments
 (0)