We have n cities labeled from 1 to n. Two different cities with labels x and y are directly connected by a bidirectional road if and only if x and y share a common divisor strictly greater than some threshold. More formally, cities with labels x and y have a road between them if there exists an integer z such that all of the following are true:
x % z == 0,y % z == 0, andz > threshold.Given the two integers, n and threshold, and an array of queries, you must determine for each queries[i] = [ai, bi] if cities ai and bi are connected directly or indirectly. (i.e. there is some path between them).
Return an array answer, where answer.length == queries.length and answer[i] is true if for the ith query, there is a path between ai and bi, or answer[i] is false if there is no path.
Example 1:
Input: n = 6, threshold = 2, queries = [[1,4],[2,5],[3,6]] Output: [false,false,true] Explanation: The divisors for each number: 1: 1 2: 1, 2 3: 1, 3 4: 1, 2, 4 5: 1, 5 6: 1, 2, 3, 6 Using the underlined divisors above the threshold, only cities 3 and 6 share a common divisor, so they are the only ones directly connected. The result of each query: [1,4] 1 is not connected to 4 [2,5] 2 is not connected to 5 [3,6] 3 is connected to 6 through path 3--6
Example 2:
Input: n = 6, threshold = 0, queries = [[4,5],[3,4],[3,2],[2,6],[1,3]] Output: [true,true,true,true,true] Explanation: The divisors for each number are the same as the previous example. However, since the threshold is 0, all divisors can be used. Since all numbers share 1 as a divisor, all cities are connected.
Example 3:
Input: n = 5, threshold = 1, queries = [[4,5],[4,5],[3,2],[2,3],[3,4]] Output: [false,false,false,false,false] Explanation: Only cities 2 and 4 share a common divisor 2 which is strictly greater than the threshold 1, so they are the only ones directly connected. Please notice that there can be multiple queries for the same pair of nodes [x, y], and that the query [x, y] is equivalent to the query [y, x].
Constraints:
2 <= n <= 1040 <= threshold <= n1 <= queries.length <= 105queries[i].length == 21 <= ai, bi <= citiesai != biWhen you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
To solve this graph connectivity problem, the brute force method is like checking if every pair of cities are connected via roads with acceptable speed limits. We will simply check every possible path between cities to see if a connection exists that meets the requirements.
Here's how the algorithm would work step-by-step:
def graph_connectivity_brute_force(number_of_cities, speed_limits, required_speed):
connected = [[False] * number_of_cities for _ in range(number_of_cities)]
# Iterate through all possible pairs of cities
for start_city in range(number_of_cities):
for end_city in range(start_city + 1, number_of_cities):
# Explore paths only if start and end are different
if start_city != end_city:
if find_path(start_city, end_city, number_of_cities, speed_limits, required_speed, [start_city]):
connected[start_city][end_city] = True
connected[end_city][start_city] = True
return connected
def find_path(current_city, end_city, number_of_cities, speed_limits, required_speed, visited):
# If current city is the destination, path exists
if current_city == end_city:
return True
# Explore neighbors with acceptable speed limits
for neighbor_city in range(number_of_cities):
#Check that the neighbor city is not in our current path
if neighbor_city not in visited:
speed = speed_limits[current_city][neighbor_city]
# Road must exist and satisfy the speed limit
if speed > required_speed:
# Recursive DFS to check the other neighbor cities
if find_path(neighbor_city, end_city, number_of_cities, speed_limits, required_speed, visited + [neighbor_city]):
return True
return FalseThe core idea is to efficiently determine if two cities are connected in a hidden graph. We use a technique that groups cities together into connected regions and then quickly checks if two cities belong to the same region.
Here's how the algorithm would work step-by-step:
def solve():
def are_connected(number_of_cities, threshold, city_a, city_b):
parent = list(range(number_of_cities + 1))
def find(city):
if parent[city] == city:
return city
parent[city] = find(parent[city])
return parent[city]
def union(city_x, city_y):
root_x = find(city_x)
root_y = find(city_y)
if root_x != root_y:
parent[root_x] = root_y
# Iterate through all city pairs.
for first_city in range(1, number_of_cities + 1):
for second_city in range(first_city + 1, number_of_cities + 1):
# Connect cities if their GCD exceeds threshold.
if gcd(first_city, second_city) > threshold:
union(first_city, second_city)
# Check connectivity after union operations.
return find(city_a) == find(city_b)
def gcd(first_number, second_number):
while second_number:
first_number, second_number = second_number, first_number % second_number
return first_number
number_of_cities_input = 6
threshold_input = 2
queries_input = [[1, 4], [2, 5], [3, 6]]
results = []
for query in queries_input:
city_a_query, city_b_query = query
results.append(are_connected(number_of_cities_input, threshold_input, city_a_query, city_b_query))
return results
def graph_connectivity_with_threshold(number_of_cities, threshold, queries):
parent = list(range(number_of_cities + 1))
def find(city):
if parent[city] == city:
return city
parent[city] = find(parent[city])
return parent[city]
def union(city_x, city_y):
root_x = find(city_x)
root_y = find(city_y)
if root_x != root_y:
parent[root_x] = root_y
# Iterate through all city pairs.
for first_city in range(1, number_of_cities + 1):
for second_city in range(first_city + 1, number_of_cities + 1):
# Connect cities if their GCD exceeds threshold.
if gcd(first_city, second_city) > threshold:
union(first_city, second_city)
results = []
for city_a, city_b in queries:
# Check connectivity after union operations.
results.append(find(city_a) == find(city_b))
return results
def gcd(first_number, second_number):
while second_number:
first_number, second_number = second_number, first_number % second_number
return first_number| Case | How to Handle |
|---|---|
| n is 0 or 1 | Return an empty list if n is 0 or 1, as no edges can be formed. |
| threshold is greater than n-1 | Return an empty list if the threshold is greater than or equal to n, as no edges can satisfy the condition. |
| threshold is 0 | Return all possible edges, as all pairs will satisfy the threshold condition. |
| n is a large number (scalability) | Union-Find is efficient and suitable for large n, but the number of edges could be n^2 in worst case (threshold = 0), potentially causing memory issues depending on output format. |
| Integer overflow when calculating gcd | Use a library gcd function that handles potential overflow or ensure the inputs to the gcd function are appropriately sized to avoid overflow. |
| All numbers from 1 to n have a gcd greater than the threshold. | Return all possible edges because all pairs are connected. |
| No two numbers share a gcd greater than the threshold. | Return an empty list, as no edges can be formed. |
| n and threshold are close, only a few edges exist | The Union-Find data structure should efficiently determine connected components even with a sparse graph. |