There is an undirected graph with n
nodes numbered from 0
to n - 1
(inclusive). You are given a 0-indexed integer array values
where values[i]
is the value of the ith
node. You are also given a 0-indexed 2D integer array edges
, where each edges[j] = [uj, vj, timej]
indicates that there is an undirected edge between the nodes uj
and vj
, and it takes timej
seconds to travel between the two nodes. Finally, you are given an integer maxTime
.
A valid path in the graph is any path that starts at node 0
, ends at node 0
, and takes at most maxTime
seconds to complete. You may visit the same node multiple times. The quality of a valid path is the sum of the values of the unique nodes visited in the path (each node's value is added at most once to the sum).
Return the maximum quality of a valid path.
Note: There are at most four edges connected to each node.
Example 1:
Input: values = [0,32,10,43], edges = [[0,1,10],[1,2,15],[0,3,10]], maxTime = 49 Output: 75 Explanation: One possible path is 0 -> 1 -> 0 -> 3 -> 0. The total time taken is 10 + 10 + 10 + 10 = 40 <= 49. The nodes visited are 0, 1, and 3, giving a maximal path quality of 0 + 32 + 43 = 75.
Example 2:
Input: values = [5,10,15,20], edges = [[0,1,10],[1,2,10],[0,3,10]], maxTime = 30 Output: 25 Explanation: One possible path is 0 -> 3 -> 0. The total time taken is 10 + 10 = 20 <= 30. The nodes visited are 0 and 3, giving a maximal path quality of 5 + 20 = 25.
Example 3:
Input: values = [1,2,3,4], edges = [[0,1,10],[1,2,11],[2,3,12],[1,3,13]], maxTime = 50 Output: 7 Explanation: One possible path is 0 -> 1 -> 3 -> 1 -> 0. The total time taken is 10 + 13 + 13 + 10 = 46 <= 50. The nodes visited are 0, 1, and 3, giving a maximal path quality of 1 + 2 + 4 = 7.
Constraints:
n == values.length
1 <= n <= 1000
0 <= values[i] <= 108
0 <= edges.length <= 2000
edges[j].length == 3
0 <= uj < vj <= n - 1
10 <= timej, maxTime <= 100
[uj, vj]
are unique.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 method for finding the maximum path quality in a graph involves exploring every possible route within the allowed time. We visit nodes one by one, trying every possible path, and calculating the quality for each path.
Here's how the algorithm would work step-by-step:
def maximum_path_quality_brute_force(values, edges, max_time):
number_of_nodes = len(values)
maximum_quality = 0
def depth_first_search(current_node, current_time, current_quality, visited_nodes):
nonlocal maximum_quality
# If we return to the starting node, update the maximum quality
if current_node == 0:
maximum_quality = max(maximum_quality, current_quality)
# Explore neighbors
for neighbor, time_to_neighbor in edges[current_node]:
if current_time + time_to_neighbor <= max_time:
new_quality = current_quality
if neighbor not in visited_nodes:
new_quality += values[neighbor]
# Add neighbor to visited nodes to track value adding
new_visited_nodes = visited_nodes.copy()
new_visited_nodes.add(neighbor)
depth_first_search(neighbor, current_time + time_to_neighbor, new_quality, new_visited_nodes)
# Represent graph as adjacency list.
adjacency_list = [[] for _ in range(number_of_nodes)]
for node1, node2, time in edges:
adjacency_list[node1].append((node2, time))
adjacency_list[node2].append((node1, time))
# Initialize visited nodes
initial_visited_nodes = {0}
# Initiate DFS from the starting node.
depth_first_search(0, 0, values[0], initial_visited_nodes)
return maximum_quality
The problem asks us to find the best path through a network, maximizing a 'quality' score while limited by a travel budget. We explore possible paths step-by-step, remembering visited locations to avoid unnecessary revisits within our budget, and keep track of the best quality found so far.
Here's how the algorithm would work step-by-step:
def maximum_path_quality(values, edges, max_time):
number_of_nodes = len(values)
adjacency_list = [[] for _ in range(number_of_nodes)]
for source, destination, time_taken in edges:
adjacency_list[source].append((destination, time_taken))
adjacency_list[destination].append((source, time_taken))
max_quality = 0
visited_counts = [0] * number_of_nodes
def depth_first_search(current_node, current_time, current_quality):
nonlocal max_quality
if current_node == 0:
max_quality = max(max_quality, current_quality)
# Explore neighbors.
for neighbor, time_to_neighbor in adjacency_list[current_node]:
if current_time + time_to_neighbor <= max_time:
# Add the neighbor's value if it hasn't been visited yet.
if visited_counts[neighbor] == 0:
visited_counts[neighbor] += 1
depth_first_search(neighbor, current_time + time_to_neighbor, current_quality + values[neighbor])
visited_counts[neighbor] -= 1
# If already visited, do not add the value again.
else:
visited_counts[neighbor] += 1
depth_first_search(neighbor, current_time + time_to_neighbor, current_quality)
visited_counts[neighbor] -= 1
# Start DFS from node 0, marking it as visited.
visited_counts[0] = 1
depth_first_search(0, 0, values[0])
return max_quality
Case | How to Handle |
---|---|
Null or empty values array | Return 0 as no path exists. |
Null or empty edges array | If maxTime allows a round trip to node 0, return values[0], otherwise return 0. |
Single node graph (values array length is 1) and no edges | If maxTime is greater or equal to 0, return values[0], otherwise 0. |
Graph with no path back to node 0 within maxTime | Return 0 as no valid path meets the criteria. |
Large graph with deep recursion exceeding stack limits | Consider iterative DFS or BFS to avoid stack overflow. |
Edges with very large time costs leading to potential integer overflow | Use long data type for time costs and accumulated path time. |
Cycle in the graph that exceeds maxTime if followed repeatedly | Implement a mechanism to prevent infinite loops by tracking visited nodes and time elapsed or limiting visit count of each node. |
maxTime is 0 and values[0] is non-zero | If a path from node 0 back to node 0 is possible within time 0, the quality should be values[0]; otherwise, it should be 0. |