Thursday, September 10, 2020

LeetCode [1548] The Most Similar Path in a Graph

 1548. The Most Similar Path in a Graph

Hard

We have n cities and m bi-directional roads where roads[i] = [ai, bi] connects city ai with city bi. Each city has a name consisting of exactly 3 upper-case English letters given in the string array names. Starting at any city x, you can reach any city y where y != x (i.e. the cities and the roads are forming an undirected connected graph).

You will be given a string array targetPath. You should find a path in the graph of the same length and with the minimum edit distance to targetPath.

You need to return the order of the nodes in the path with the minimum edit distance, The path should be of the same length of targetPath and should be valid (i.e. there should be a direct road between ans[i] and ans[i + 1]). If there are multiple answers return any one of them.

The edit distance is defined as follows:

Follow-up: If each node can be visited only once in the path, What should you change in your solution?

 

Example 1:

Input: n = 5, roads = [[0,2],[0,3],[1,2],[1,3],[1,4],[2,4]], names = ["ATL","PEK","LAX","DXB","HND"], targetPath = ["ATL","DXB","HND","LAX"]
Output: [0,2,4,2]
Explanation: [0,2,4,2], [0,3,0,2] and [0,3,1,2] are accepted answers.
[0,2,4,2] is equivalent to ["ATL","LAX","HND","LAX"] which has edit distance = 1 with targetPath.
[0,3,0,2] is equivalent to ["ATL","DXB","ATL","LAX"] which has edit distance = 1 with targetPath.
[0,3,1,2] is equivalent to ["ATL","DXB","PEK","LAX"] which has edit distance = 1 with targetPath.

Example 2:

Input: n = 4, roads = [[1,0],[2,0],[3,0],[2,1],[3,1],[3,2]], names = ["ATL","PEK","LAX","DXB"], targetPath = ["ABC","DEF","GHI","JKL","MNO","PQR","STU","VWX"]
Output: [0,1,0,1,0,1,0,1]
Explanation: Any path in this graph has edit distance = 8 with targetPath.

Example 3:

Input: n = 6, roads = [[0,1],[1,2],[2,3],[3,4],[4,5]], names = ["ATL","PEK","LAX","ATL","DXB","HND"], targetPath = ["ATL","DXB","HND","DXB","ATL","LAX","PEK"]
Output: [3,4,5,4,3,2,1]
Explanation: [3,4,5,4,3,2,1] is the only path with edit distance = 0 with targetPath.
It's equivalent to ["ATL","DXB","HND","DXB","ATL","LAX","PEK"]

 

Constraints:

  • 2 <= n <= 100
  • m == roads.length
  • n - 1 <= m <= (n * (n - 1) / 2)
  • 0 <= ai, bi <= n - 1
  • ai != bi 
  • The graph is guaranteed to be connected and each pair of nodes may have at most one direct road.
  • names.length == n
  • names[i].length == 3
  • names[i] consists of upper-case English letters.
  • There can be two cities with the same name.
  • 1 <= targetPath.length <= 100
  • targetPath[i].length == 3
  • targetPath[i] consists of upper-case English letters.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
class Solution {
    public List<Integer> mostSimilar(int n, int[][] roads, String[] names, String[] targetPath) {
        int m = targetPath.length;
        if(m==0||n==0) return new ArrayList<>();
        int[][] dp = new int[m][n];
        int[][] prev = new int[m][n];
        int[][] graph = new int[n][n];

        for(int[] node : roads){
            int u = node[0], v = node[1];
            graph[u][v] = 1;
            graph[v][u] = 1;
        }

        for(int i=0; i<m; ++i) Arrays.fill(dp[i], m);
        for(int j=0; j<n; ++j) dp[0][j] = names[j].equals(targetPath[0])?0:1;

        for(int i=1; i<m; ++i){
            for(int j=0; j<n; ++j){
                for(int p=0; p<n; ++p){
                    //find i_len path with min edit distance
                    if(graph[p][j]==1){//p-->j
                        if(dp[i-1][p]<dp[i][j]){
                            dp[i][j] = dp[i-1][p];
                            prev[i][j] = p;
                        }
                    }
                }
                dp[i][j] += names[j].equals(targetPath[i])?0:1;
            }
        }

        //find the min path
        int min = m+1;
        int tail = n;
        for(int j=0; j<n; ++j){
            if(min>dp[m-1][j]){
                min = dp[m-1][j];
                tail = j;
            }
        }

        List<Integer> list = new ArrayList<>();
        list.add(tail);
        int l = m-1;
        while(l>=1){
            tail = prev[l][tail];
            list.add(0, tail);
            l--;
        }

        return list;
    }
}

No comments:

Post a Comment