There are 2 lists A and B containing (x, y) pairs of the same length,
A= [(x1, y1), (x2, y2),...,(xn, yn)]
B= [(x'1, y'1), (x'2, y'2),...,(x'n, y'n)]
x in A and B are nondecreasing order
x1<=x2<=x3 ...<=xn
x'1<=x'2<=x'3 ...<=x'n
for index 0<=i<n
we also want to make a[i][1]<b[i][1]
What do we do?
test case1
a= [(1, 0), (1, 1), (1, 7), (1, 5) ]
b= [(1, 7), (1, 9), (2, 3), (4, 1) ]
#in this case you can rearrange a
a= [(1, 5), (1, 7), (1, 1), (1, 0)]
b= [(1, 7), (1, 9), (2, 3), (4, 1) ]
test case2
a= [(1, 0), (2, 1), (3, 7), (3, 5) ]
b= [(2, 7), (2, 9), (2, 3), (2, 1) ]
#in this case you can rearrange b
a= [(1, 0), (2, 1), (3, 7), (3, 5) ]
b= [(2, 1), (2, 3), (2, 9), (2, 7) ]
#invalid test case
a = [(1, 0), (2, 1), (3, 7), (4, 5)]
b = [(2, 7), (3, 0), (4, 3), (5, 1)]
compute all permutations and first check if x values are all increasing. If that check is true, if the y values of b >y values oa, then we can just return those 2 lists
def rearrange_lists_ultra_simple(a, b):
"""
Ultra simple: Just try every possible rearrangement (very inefficient!)
"""
# Try all permutations of both arrays
for a_perm in permutations(a):
for b_perm in permutations(b):
# Check if x-values are still non-decreasing
a_valid = all(a_perm[i][0] <= a_perm[i+1][0] for i in range(len(a_perm)-1))
b_valid = all(b_perm[i][0] <= b_perm[i+1][0] for i in range(len(b_perm)-1))
if a_valid and b_valid:
# Check if y-constraint is satisfied
if all(a_perm[i][1] < b_perm[i][1] for i in range(len(a_perm))):
return list(a_perm), list(b_perm)
raise ValueError("No valid arrangement exists")
the perm time is n!
we are doing it twice and have n check
so time is n! ^2 * n time
n space
we are essentially filling avaialable values to be compared. If the x values of list a and b match,
1) we match the biggest avaialble value of y in a to the smallest value of y in b.
2) when we run out of elements in the available set, we populate that set with the current value but if we cant populate we raise exception
def rearrange_lists(a, b):
n = len(a)
if n != len(b):
raise ValueError("Lists must have the same length")
# Create sets to track available elements with their original indices
available_a = set()
available_b = set()
result_a = [None] * n
result_b = [None] * n
def populate_group(available_set, arr, start_idx):
"""Populate available set with elements from the same x-group"""
if start_idx >= len(arr):
return start_idx
current_x = arr[start_idx][0]
idx = start_idx
while idx < len(arr) and arr[idx][0] == current_x:
available_set.add((arr[idx][1], idx)) # (y_value, original_index)
idx += 1
return idx
a_idx = 0 # Current position in list a
b_idx = 0 # Current position in list b
result_idx = 0 # Current position in result
while result_idx < n:
# Populate available sets if empty
if not available_a:
a_idx = populate_group(available_a, a, a_idx)
if not available_b:
b_idx = populate_group(available_b, b, b_idx)
# If both sets are empty, we're done
if not available_a and not available_b:
break
# If one set is empty but the other isn't, no solution exists
if not available_a or not available_b:
raise ValueError("No valid arrangement exists")
# Find the smallest available element in B
min_b = min(available_b)
smallest_b_y, b_original_idx = min_b
available_b.remove(min_b)
# Find the largest available element in A that's smaller than smallest_b_y
valid_a_elements = [(y, idx) for y, idx in available_a if y < smallest_b_y]
if not valid_a_elements:
raise ValueError("No valid arrangement exists")
# Choose the largest valid element from A
largest_valid_a = max(valid_a_elements)
largest_a_y, a_original_idx = largest_valid_a
available_a.remove(largest_valid_a)
# Store the results
result_a[result_idx] = a[a_original_idx]
result_b[result_idx] = b[b_original_idx]
result_idx += 1
return result_a, result_b
in the main while loop there is n^2 time so thats the main
n space