Skip to content

Commit 34024dc

Browse files
Add 'Merge Intervals'
1 parent e417108 commit 34024dc

File tree

3 files changed

+88
-0
lines changed

3 files changed

+88
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ A collection of LeetCode solutions
6060

6161
[Maximum Subarray](./src/maximum_subarray.py)
6262

63+
[Merge Intervals](./src/merge_intervals.py)
64+
6365
[Merge k Sorted Lists](./src/merge_k_sorted_lists.py)
6466

6567
[Merge Sorted Array](./src/merge_sorted_array.py)

src/merge_intervals.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
"""
2+
56. Merge Intervals
3+
4+
https://leetcode.com/problems/merge-intervals
5+
6+
NOTES
7+
* A common routine for interval problems is to sort the array of intervals
8+
by each interval's starting index.
9+
"""
10+
11+
12+
class Solution:
13+
def merge(self, intervals: list[list[int]]) -> list[list[int]]:
14+
if not intervals:
15+
return []
16+
sorted_intervals = sorted(intervals)
17+
ans: list[list[int]] = [sorted_intervals[0]]
18+
# p1 is a pointer into ans. p2 is a pointer into sorted_intervals.
19+
p1, p2 = 0, 1
20+
while p2 < len(sorted_intervals):
21+
if overlap(ans[p1], sorted_intervals[p2]):
22+
ans[p1] = merge(ans[p1], sorted_intervals[p2])
23+
else:
24+
ans.append(sorted_intervals[p2])
25+
p1 += 1
26+
p2 += 1
27+
return ans
28+
29+
30+
def overlap(a: list[int], b: list[int]) -> bool:
31+
"""
32+
Returns True if `a` and `b` overlap, otherwise returns False.
33+
"""
34+
return a[0] <= b[1] and b[0] <= a[1]
35+
36+
37+
def merge(a: list[int], b: list[int]) -> list[int]:
38+
"""
39+
Merges two intervals (`a` and `b`).
40+
"""
41+
return [min(a[0], b[0]), max(a[1], b[1])]
42+
43+
44+
class OptimizedSolution:
45+
"""
46+
Since the intervals are already sorted, we only need to check if the end
47+
index of the last interval is greater than or equal to the start index of
48+
the current interval.
49+
"""
50+
def merge(self, intervals: list[list[int]]) -> list[list[int]]:
51+
intervals.sort(key=lambda x: x[0])
52+
merged: list[list[int]] = []
53+
for interval in intervals:
54+
if not merged or merged[-1][1] < interval[0]:
55+
merged.append(interval)
56+
else:
57+
merged[-1][1] = max(merged[-1][1], interval[1])
58+
return merged

tests/test_merge_intervals.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""
2+
56. Merge Intervals
3+
4+
https://leetcode.com/problems/merge-intervals
5+
"""
6+
from unittest import TestCase
7+
8+
from src.merge_intervals import Solution, OptimizedSolution
9+
10+
11+
class TestSolution(TestCase):
12+
def test_1(self):
13+
exp = [[1, 6], [8, 10], [15, 18]]
14+
assert Solution().merge([[1, 3], [2, 6], [8, 10], [15, 18]]) == exp
15+
16+
def test_2(self):
17+
exp = [[1, 5]]
18+
assert Solution().merge([[1, 4], [4, 5]]) == exp
19+
20+
21+
class TestOptimizedSolution(TestCase):
22+
def test_1(self):
23+
exp = [[1, 6], [8, 10], [15, 18]]
24+
assert OptimizedSolution().merge([[1, 3], [2, 6], [8, 10], [15, 18]]) == exp
25+
26+
def test_2(self):
27+
exp = [[1, 5]]
28+
assert OptimizedSolution().merge([[1, 4], [4, 5]]) == exp

0 commit comments

Comments
 (0)