The destination city is a city that appears as an endpoint but never as a starting point in any path. For each destination in the paths, we can check whether it ever appears as a starting city. The city that never starts a path is our answer.
Algorithm
Iterate through each path and consider its destination city.
For each destination, iterate through all paths again to check if this city appears as a starting point.
If the destination never appears as a starting point in any path, return it as the answer.
Return an empty string if no destination city is found (though the problem guarantees one exists).
classSolution:defdestCity(self, paths: List[List[str]])->str:for i inrange(len(paths)):
flag =Truefor j inrange(len(paths)):if paths[i][1]== paths[j][0]:
flag =Falsebreakif flag:return paths[i][1]return""
Time & Space Complexity
Time complexity: O(n2)
Space complexity: O(1)
2. Hash Set
Intuition
Instead of checking each destination against all starting points in O(n) time, we can store all starting cities in a hash set for O(1) lookup. Any destination city that is not in the set of starting cities must be the final destination.
Algorithm
Create a hash set and add all starting cities (the first element of each path) to it.
Iterate through all paths and check each destination city (the second element).
If a destination city is not found in the hash set, return it as the answer.
The first destination not in the set is the final destination city.
classSolution:defdestCity(self, paths: List[List[str]])->str:
s =set()for p in paths:
s.add(p[0])for p in paths:if p[1]notin s:return p[1]
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(n)
3. Hash Map
Intuition
We can model the paths as a linked chain where each city points to its next destination. By building this chain in a hash map and following the links from any starting city, we will eventually reach the final destination, which has no outgoing path.
Algorithm
Build a hash map where each key is a starting city and its value is the destination city.
Start with the first city from the first path.
Keep following the chain: while the current city exists as a key in the map, move to its destination.
When the current city is not a key in the map, it means there is no outgoing path from it, return it as the destination city.
classSolution:defdestCity(self, paths: List[List[str]])->str:
mp ={p[0]: p[1]for p in paths}
start = paths[0][0]while start in mp:
start = mp[start]return start
Time & Space Complexity
Time complexity: O(n)
Space complexity: O(n)
Common Pitfalls
Adding Both Cities to the Set
When using the hash set approach, only starting cities should be added to the set. Adding both starting and ending cities defeats the purpose since you need to find which destination is never a starting point.
# Wrong - adds both citiesfor p in paths:
s.add(p[0])
s.add(p[1])# Incorrect: this includes destinations# Correct - only add starting citiesfor p in paths:
s.add(p[0])
Checking Starting Cities Instead of Destinations
A common logic error is checking if starting cities are absent from the set of destinations, rather than checking if destinations are absent from the set of starting cities.
# Wrong - checking the wrong direction
s =set(p[1]for p in paths)# Set of destinationsfor p in paths:if p[0]notin s:# Looking for start with no incoming pathreturn p[0]# Correct - find destination with no outgoing path
s =set(p[0]for p in paths)# Set of starting citiesfor p in paths:if p[1]notin s:# Destination that is never a startreturn p[1]