Destination City

🏠 ⬅️ ➡️

You are given the array paths, where paths[i] = [cityAi, cityBi] means there exists a direct path going from cityAi to cityBi. Return the destination city, that is, the city without any path outgoing to another city.

It is guaranteed that the graph of paths forms a line without any loop, therefore, there will be exactly one destination city.

Example 1:

Input: paths = [[ "London ", "New York "],[ "New York ", "Lima "],[ "Lima ", "Sao Paulo "]] Output: "Sao Paulo " Explanation: Starting at "London " city you will reach "Sao Paulo " city which is the destination city. Your trip consist of: "London " -> "New York " -> "Lima " -> "Sao Paulo ".

Example 2:

Input: paths = [[ "B ", "C "],[ "D ", "B "],[ "C ", "A "]] Output: "A " Explanation: All possible trips are: "D " -> "B " -> "C " -> "A ". "B " -> "C " -> "A ". "C " -> "A ". "A ". Clearly the destination city is "A ".

Example 3:

Input: paths = [[ "A ", "Z "]] Output: "Z "

Constraints:

  • 1 <= paths.length <= 100
  • paths[i].length == 2
  • 1 <= cityAi.length, cityBi.length <= 10
  • cityAi != cityBi
  • All strings consist of lowercase and uppercase English letters and the space character.

Note: This problem is from LeetCode.
Compiled
Executed
Correct
program main
    implicit none

    integer :: i, j
    character(len=10) :: paths(10,2)
    character(len=10) :: dest_city

    ! Example 1
    paths(1,:) = ['London ', 'New York']
    paths(2,:) = ['New York ', 'Lima']
    paths(3,:) = ['Lima ', 'Sao Paulo']
    call solve(paths, dest_city)
    write(*,'(a)') trim(dest_city) // ' ' // 'Sao Paulo'

    ! Example 2
    paths(:,1) = ['B', 'C', 'D']
    paths(:,2) = ['C', 'A', 'B']
    call solve(paths, dest_city)
    write(*,'(a)') trim(dest_city) // ' ' // 'A'

    ! Example 3
    paths(:,:) = ['A', 'Z']
    call solve(paths, dest_city)
    write(*,'(a)') trim(dest_city) // ' ' // 'Z'

contains

subroutine solve(paths, dest_city)
    implicit none
    character(len=10), intent(in) :: paths(:,:)
    character(len=10), intent(out) :: dest_city
    logical :: visited(size(paths,1))
    integer :: i, j

    visited(:) = .false.
    do i = 1, size(paths,1)
        if (.not. visited(i)) then
            do j = 1, size(paths,1)
                if (visited(j)) cycle
                if (paths(j,1) == paths(i,2)) then
                    visited(j) = .true.
                    exit
                end if
            end do
        end if
    end do

    do i = 1, size(paths,1)
        if (.not. visited(i)) then
            dest_city = paths(i,1)
            return
        end if
    end do
end subroutine solve

end program main
Compiled
Executed
Correct
! Declare variables
integer :: i, j, k, n, m
character(len=10) :: cityA, cityB, cityC
character(len=10), dimension(:,:), allocatable :: paths
logical, dimension(:), allocatable :: visited

! Read input
read(*,*) n
allocate(paths(n,2))
do i=1,n
    read(*,*) paths(i,1), paths(i,2)
end do

! Initialize variables
m = 0
allocate(visited(n))
visited = .false.

! Find destination city
do i=1,n
    if (visited(i)) cycle
    cityA = paths(i,1)
    cityB = paths(i,2)
    do j=1,n
        if (visited(j)) cycle
        cityC = paths(j,1)
        if (cityC == cityB) then
            visited(j) = .true.
            m = m + 1
            exit
        end if
    end do
end do

! Print output
if (m == 1) then
    write(*,*) cityA
else
    write(*,*) "Destination city not found"
end if

! Deallocate memory
deallocate(paths)
deallocate(visited)

end
🌐 Data from online sources
from collections import deque
from collections import defaultdict

def watched_videos_by_friends(watched_videos, friends, id, level):
    visited = set()
    q = deque([(id, 0)])
    video_freq = defaultdict(int)

    while q:
        current_id, current_level = q.popleft()

        if current_level == level:
            for video in watched_videos[current_id]:
                video_freq[video] += 1
        elif current_level < level:
            for friend_id in friends[current_id]:
                if friend_id not in visited:
                    visited.add(friend_id)
                    q.append((friend_id, current_level + 1))

    result = sorted(video_freq.keys(), key=lambda x: (video_freq[x], x))

    return result

The algorithm works as follows: 1. Initialize a visited set to keep track of the visited person ids, and a queue, which stores pairs containing the person id and the level or search depth. 2. Push the given id and level 0 onto the queue and mark the id visited. 3. While there are still unprocessed items in the queue, check the current level of the person in the queue. a) If the current level is equal to the given level, increment the count of each video watched by this person in a frequency map. b) If the current level is less than the given level, iterate through the friends of the current person and push those friends' ids in the queue with the incremented level if they haven't been visited yet, and mark them visited. 4. Create a result list from the keys in the frequency map. 5. Sort the result list based on the frequency of the videos and their names. 6. Return the sorted result list.

This algorithm has a breadth-first search (BFS) traversal through the connections, which helps in finding the shortest path.

🌐 Data from online sources
#include <vector>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <algorithm>
#include <string>

using namespace std;

vector<string> watchedVideosByFriends(vector<vector<string>>& watchedVideos, vector<vector<int>>& friends, int id, int level) {
    unordered_set<int> visited;
    queue<pair<int, int>> q;
    unordered_map<string, int> video_freq;

    q.push({id, 0});
    visited.insert(id);

    while (!q.empty()) {
        int current_id = q.front().first;
        int current_level = q.front().second;
        q.pop();

        if (current_level == level) {
            for (const string& video : watchedVideos[current_id]) {
                video_freq[video]++;
            }
        } else if (current_level < level) {
            for (int friend_id : friends[current_id]) {
                if (visited.find(friend_id) == visited.end()) {
                    visited.insert(friend_id);
                    q.push({friend_id, current_level + 1});
                }
            }
        }
    }

    vector<string> result;
    for (const auto& p : video_freq) {
        result.push_back(p.first);
    }

    sort(result.begin(), result.end(), [&video_freq](const string& a, const string& b) {
        if (video_freq[a] == video_freq[b]) {
            return a < b;
        } else {
            return video_freq[a] < video_freq[b];
        }
    });

    return result;
}

The algorithm works as follows: 1. Initialize a visited set to keep track of the visited person ids, and a queue, which stores pairs containing the person id and the level or search depth. 2. Push the given id and level 0 onto the queue and mark the id visited. 3. While there are still unprocessed items in the queue, check the current level of the person in the queue. a) If the current level is equal to the given level, increment the count of each video watched by this person in a frequency map. b) If the current level is less than the given level, iterate through the friends of the current person and push those friends' ids in the queue with the incremented level if they haven't been visited yet, and mark them visited. 4. Create a result list from the keys in the frequency map. 5. Sort the result list based on the frequency of the videos and their names. 6. Return the sorted result list.

This algorithm has a breadth-first search (BFS) traversal through the connections, which helps in finding the shortest path.