There are n
cities numbered from 0
to n-1
. You are given an array edges
where edges[i] = [from_i, to_i, weight_i]
represents a bidirectional and weighted edge between cities from_i
and to_i
, and you are given an integer distanceThreshold
.
Your task is to find the city with the smallest number of cities that are reachable through some path and whose distance is at most distanceThreshold
. If there are multiple such cities, return the city with the greatest number.
Note that the distance of a path connecting cities i and j is equal to the sum of the edges' weights along that path.
Example 1:
Consider n = 4
, edges = [[0,1,3],[1,2,1],[1,3,4],[2,3,1]]
, and distanceThreshold = 4
.
The graph can be visualized as follows:
0 --3-- 1
| / |
| / |
| / |
3 1 4
| / |
| / |
|/ |
2 --1-- 3
The neighboring cities at a distanceThreshold = 4
for each city are:
Both cities 0 and 3 have 2 neighboring cities at a distanceThreshold = 4
, but you should return city 3 since it has the greatest number.
Example 2:
Consider n = 5
, edges = [[0,1,2],[0,4,8],[1,2,3],[1,4,2],[2,3,1],[3,4,1]]
, and distanceThreshold = 2
.
The neighboring cities at a distanceThreshold = 2
for each city are:
The city 0 has 1 neighboring city at a distanceThreshold = 2
.
Constraints:
2 <= n <= 100
1 <= edges.length <= n * (n - 1) / 2
edges[i].length == 3
0 <= from_i < to_i < n
1 <= weight_i, distanceThreshold <= 10^4
(from_i, to_i)
are distinct.When 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:
The brute force approach here is like checking every single city to see which one has the fewest reachable neighbors within a certain distance. We will look at each city one by one and figure out how many other cities are close enough.
Here's how the algorithm would work step-by-step:
def find_the_city(
number_of_cities, edges, distance_threshold
):
smallest_number_reachable_cities = number_of_cities
city_with_smallest_number_reachable_cities = -1
for starting_city in range(number_of_cities):
number_reachable_cities = 0
for other_city in range(number_of_cities):
if starting_city == other_city:
continue
distance = find_distance(
starting_city, other_city, number_of_cities, edges
)
# Count if the other city is reachable from the starting city
if distance <= distance_threshold:
number_reachable_cities += 1
# Update city if smaller neighbor count or tie with larger city
if (
number_reachable_cities
< smallest_number_reachable_cities
):
smallest_number_reachable_cities = number_reachable_cities
city_with_smallest_number_reachable_cities = starting_city
elif (
number_reachable_cities
== smallest_number_reachable_cities
):
city_with_smallest_number_reachable_cities = max(
city_with_smallest_number_reachable_cities,
starting_city,
)
return city_with_smallest_number_reachable_cities
def find_distance(city1, city2, number_of_cities, edges):
distances = [
[float('inf')] * number_of_cities for _ in range(number_of_cities)
]
for i in range(number_of_cities):
distances[i][i] = 0
for edge in edges:
city_a, city_b, weight = edge
distances[city_a][city_b] = weight
distances[city_b][city_a] = weight
# Floyd-Warshall algorithm to find shortest paths
for intermediate_city in range(number_of_cities):
for i in range(number_of_cities):
for j in range(number_of_cities):
distances[i][j] = min(
distances[i][j],
distances[i][intermediate_city]
+ distances[intermediate_city][j],
)
return distances[city1][city2]
The problem asks to find a city with the fewest reachable cities within a certain distance. Instead of calculating distances repeatedly, the most efficient approach leverages a well-known algorithm to pre-compute all pairwise distances between cities, then quickly counts the reachable cities for each city.
Here's how the algorithm would work step-by-step:
def find_the_city(number_of_cities, edges, distance_threshold):
distance_matrix = [[float('inf')] * number_of_cities for _ in range(number_of_cities)]
for i in range(number_of_cities):
distance_matrix[i][i] = 0
for start_node, end_node, weight in edges:
distance_matrix[start_node][end_node] = weight
distance_matrix[end_node][start_node] = weight
# Floyd-Warshall Algorithm to calculate all-pairs shortest paths.
for intermediate_node in range(number_of_cities):
for start_node in range(number_of_cities):
for end_node in range(number_of_cities):
distance_matrix[start_node][end_node] = min(
distance_matrix[start_node][end_node],
distance_matrix[start_node][intermediate_node] + distance_matrix[intermediate_node][end_node]
)
smallest_number_of_reachable_cities = number_of_cities
city_with_smallest_number_of_reachable_cities = -1
# Iterate through each city to find the one with the smallest number of reachable cities.
for current_city in range(number_of_cities):
number_of_reachable_cities = 0
for other_city in range(number_of_cities):
if distance_matrix[current_city][other_city] <= distance_threshold:
number_of_reachable_cities += 1
# Track the city with the fewest reachable cities.
if number_of_reachable_cities <= smallest_number_of_reachable_cities:
# Break ties by selecting the city with the highest index.
if number_of_reachable_cities < smallest_number_of_reachable_cities:
smallest_number_of_reachable_cities = number_of_reachable_cities
city_with_smallest_number_of_reachable_cities = current_city
else:
city_with_smallest_number_of_reachable_cities = current_city
return city_with_smallest_number_of_reachable_cities
Case | How to Handle |
---|---|
Empty graph (n = 0 or edges is empty) | Return 0, as the problem states to return a city even if no connections exist. |
Single node graph (n = 1, edges is empty) | Return 0, as it's the only city and has no neighbors. |
Threshold distance is zero. | Only cities connected directly to themselves (if such edges exist) will be counted as neighbors, otherwise none. |
All edge weights are greater than the threshold. | Every city will have zero reachable cities within the threshold distance. |
Complete graph with all edge weights equal to 1 and threshold < 1. | No cities will be reachable, return the city with the smallest index (n-1). |
Graph with disconnected components. | The algorithm must correctly compute the number of reachable nodes within the threshold for each component separately. |
Large graph (n approaching constraints) to test performance | Floyd-Warshall algorithm or Dijkstra with priority queue are preferred for efficiency. |
Integer overflow in distance calculations when edge weights or threshold are large. | Use long data type to store intermediate distances to avoid potential overflow. |