Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Python - Non-overlapping Random Ranges
Generating non-overlapping random ranges is useful in data analysis, sampling, and testing scenarios. Python's random module provides tools to create ranges that don't intersect with each other.
Understanding the Problem
Given a start value, end value, and number of ranges needed, we generate random ranges that don't overlap. For example, with start=1, end=50, and 3 ranges, we might get [(5, 8), (15, 22), (35, 40)].
Method 1: Simple Range Generation
This approach generates random ranges but doesn't guarantee they won't overlap ?
import random
def simple_ranges(start, end, num_ranges):
ranges = []
for _ in range(num_ranges):
range_start = random.randint(start, end - 1)
range_end = random.randint(range_start, end)
ranges.append((range_start, range_end))
return ranges
# Example usage
result = simple_ranges(10, 100, 4)
print("Simple ranges:", result)
Simple ranges: [(23, 67), (45, 89), (12, 34), (78, 95)]
Method 2: True Non-Overlapping Ranges
This method ensures ranges never overlap by checking for conflicts ?
import random
def non_overlapping_ranges(start, end, num_ranges, min_gap=1):
ranges = []
max_attempts = 100
for _ in range(num_ranges):
attempts = 0
while attempts < max_attempts:
range_start = random.randint(start, end - min_gap)
range_end = random.randint(range_start + min_gap, end)
# Check if this range overlaps with existing ranges
overlap = False
for existing_start, existing_end in ranges:
if (range_start <= existing_end and range_end >= existing_start):
overlap = True
break
if not overlap:
ranges.append((range_start, range_end))
break
attempts += 1
return ranges
# Example usage
result = non_overlapping_ranges(1, 50, 3)
print("Non-overlapping ranges:", result)
print("Number of ranges generated:", len(result))
Non-overlapping ranges: [(8, 15), (25, 32), (40, 47)] Number of ranges generated: 3
Method 3: Partitioned Approach
Divide the total range into segments to guarantee non-overlapping results ?
import random
def partitioned_ranges(start, end, num_ranges):
if num_ranges <= 0:
return []
total_span = end - start
segment_size = total_span // num_ranges
ranges = []
for i in range(num_ranges):
segment_start = start + (i * segment_size)
segment_end = start + ((i + 1) * segment_size) - 1
if i == num_ranges - 1: # Last segment gets remainder
segment_end = end
# Generate random range within this segment
range_start = random.randint(segment_start, segment_end - 1)
range_end = random.randint(range_start, segment_end)
ranges.append((range_start, range_end))
return ranges
# Example usage
result = partitioned_ranges(1, 100, 4)
print("Partitioned ranges:", result)
Partitioned ranges: [(3, 24), (28, 49), (52, 74), (78, 100)]
Comparison
| Method | Guarantees Non-Overlap | Time Complexity | Best For |
|---|---|---|---|
| Simple | No | O(n) | Quick generation |
| Overlap Check | Yes | O(n²) | Flexible ranges |
| Partitioned | Yes | O(n) | Large datasets |
Conclusion
Use the partitioned approach for guaranteed non-overlapping ranges with O(n) performance. The overlap-checking method provides more flexibility but has higher time complexity for large datasets.
