📌  相关文章
📜  数组中两个节点之间的最短路径,如二叉树的表示

📅  最后修改于: 2022-05-13 01:57:18.119000             🧑  作者: Mango

数组中两个节点之间的最短路径,如二叉树的表示

考虑一棵二叉树,其中每个节点都有两个子节点,除了叶节点。如果一个节点被标记为“v”,那么它的右孩子将被标记为 2v+1,而左孩子将被标记为 2v。根标记为
给定两个标记为 i 和 j 的节点,任务是找到最短距离和从 i 到 j 的路径。并从根节点打印节点 i 和节点 j 的路径。

例子:

这个问题主要是二叉树的两个给定键之间的查找距离的扩展。在这里,我们不仅找到了最短距离,还找到了路径。
两个节点 i 和 j 之间的距离将等于 dist(i, LCA(i, j)) + dist(j, LCA(i, j)) 其中 LCA 表示标记为 i 和 j 的节点的最低共同祖先.如果数字 x 以二进制形式表示,则 2*x 可以通过将 0 附加到 x 的二进制表示,而 2x+1 可以通过将 1 附加到 x 的二进制表示来表示。这是因为当我们追加 0 时,所有以 x 的二进制形式存在的项左移,所以当我们追加 1 时,它会类似地翻倍,我们得到 2x+1。假设一个节点的二进制表示是 1010,这告诉我们这个节点从根开始的路径。第一项 '1' 代表根 第二项 0 代表左转,第三项 1 代表从前一个节点向右转,最后,0 代表左转。

二进制形式的节点 10 是 1010,二进制形式的 13 是 1101 其次,任何节点的二进制表示的长度也说明了它在二叉树中的级别。假设 i 的二进制表示是 m 长度并且是i_1       [特克斯]i_2 [/特克斯]… i_m       并且节点 j 的二进制表示为 n 长度j_1       [特克斯]j_2 [/特克斯]…… j_n       .
因此,我们从根知道 i 和 j 的路径。找出 k 使得对于所有 p<=k i_p       = j_p       .这是二进制形式的 i 和 j 的 LCA。所以 dist(i, LCA(i, j)) 将是 m – k 并且 dist(j, LCA(i, j)) = n – k。所以答案将是 m + n – 2k。并且打印路径也不是一个大问题,只需将 i 的路径存储到 LCA 并将 j 的路径存储到 LCA 并将它们连接起来。

C++
// C++ representation of finding shortest
// distance between node i and j
#include 
using namespace std;
 
// prints the path between node i and node j
void ShortestPath(int i, int j, int k, int m, int n)
{
    // path1 stores path of node i to lca and
    // path2 stores path of node j to lca
    vector path1, path2;
    int x = m - 1;
 
    // push node i in path1
    path1.push_back(i);
 
    // keep pushing parent of node labelled
    // as i to path1 until lca is reached
    while (x != k) {
        path1.push_back(i / 2);
        i = i / 2;
        x--;
    }
    int y = n - 1;
 
    // push node j to path2
    path2.push_back(j);
 
    // keep pushing parent of node j till
    // lca is reached
    while (y != k)
    {
        path2.push_back(j / 2);
        j = j / 2;
        y--;
    }
 
    // printing path from node i to lca
    for (int l = 0; l < path1.size(); l++)
        cout << path1[l] << " ";
 
    // printing path from lca to node j
    for (int l = path2.size() - 2; l >= 0; l--)
        cout << path2[l] << " ";
    cout << endl;
}
 
// returns the shortest distance between
// nodes labelled as i and j
int ShortestDistance(int i, int j)
{
    // vector to store binary form of i and j
    vector v1, v2;
 
    // finding binary form of i and j
    int p1 = i;
    int p2 = j;
    while (i != 0)
    {
        v1.push_back(i % 2);
        i = i / 2;
    }
    while (j != 0) {
        v2.push_back(j % 2);
        j = j / 2;
    }
 
    // as binary form will be in reverse order
    // reverse the vectors
    reverse(v1.begin(), v1.end());
    reverse(v2.begin(), v2.end());
 
    // finding the k that is lca (i, j)
    int m = v1.size(), n = v2.size(), k = 0;
    if (m < n)
    {
        while (k < m && v1[k] == v2[k])
            k++;
    }
    else {
        while (k < n && v1[k] == v2[k])
            k++;
    }
 
    ShortestPath(p1, p2, k - 1, m, n);
    return m + n - 2 * k;
}
 
// Driver Code
int main()
{
    cout << ShortestDistance(1, 2) << endl;
    cout << ShortestDistance(4, 3) << endl;
    return 0;
}


Java
// Java representation of finding shortest
// distance between node i and j
import java.util.*;
 
class GFG
{
     
// prints the path between node i and node j
static void ShortestPath(int i, int j, int k, int m,
                                    int n)
{
    // path1 stores path of node i to lca and
    // path2 stores path of node j to lca
    Vector path1=new Vector(),
                    path2=new Vector();
    int x = m - 1;
 
    // push node i in path1
    path1.add(i);
 
    // keep pushing parent of node labelled
    // as i to path1 until lca is reached
    while (x != k)
    {
        path1.add(i / 2);
        i = i / 2;
        x--;
    }
    int y = n - 1;
 
    // push node j to path2
    path2.add(j);
 
    // keep pushing parent of node j till
    // lca is reached
    while (y != k)
    {
        path2.add(j / 2);
        j = j / 2;
        y--;
    }
 
    // printing path from node i to lca
    for (int l = 0; l < path1.size(); l++)
        System.out.print( path1.get(l) + " ");
 
    // printing path from lca to node j
    for (int l = path2.size() - 2; l >= 0; l--)
        System.out.print( path2.get(l) + " ");
    System.out.println();
}
 
// returns the shortest distance between
// nodes labelled as i and j
static int ShortestDistance(int i, int j)
{
    // vector to store binary form of i and j
    Vector v1=new Vector(),
                    v2=new Vector();
 
    // finding binary form of i and j
    int p1 = i;
    int p2 = j;
    while (i != 0)
    {
        v1.add(i % 2);
        i = i / 2;
    }
    while (j != 0)
    {
        v2.add(j % 2);
        j = j / 2;
    }
 
    // as binary form will be in reverse order
    // reverse the vectors
    Collections.reverse(v1);
    Collections.reverse(v2);
 
    // finding the k that is lca (i, j)
    int m = v1.size(), n = v2.size(), k = 0;
    if (m < n)
    {
        while (k < m && v1.get(k) == v2.get(k))
            k++;
    }
    else
    {
        while (k < n && v1.get(k) == v2.get(k))
            k++;
    }
 
    ShortestPath(p1, p2, k - 1, m, n);
    return m + n - 2 * k;
}
 
// Driver code
public static void main(String args[])
{
    System.out.println( ShortestDistance(1, 2) );
    System.out.println(ShortestDistance(4, 3) );
}
}
 
// This code is contributed by Arnab Kundu


Python3
# Python3 representation of finding
# shortest distance between node i and j
 
# Prints the path between node i and node j
def ShortestPath(i, j, k, m, n):
 
    # path1 stores path of node i to lca and
    # path2 stores path of node j to lca
    path1, path2 = [], []
    x = m - 1
 
    # push node i in path1
    path1.append(i)
 
    # keep pushing parent of node labelled
    # as i to path1 until lca is reached
    while x != k:
        path1.append(i // 2)
        i = i // 2
        x -= 1
     
    y = n - 1
 
    # push node j to path2
    path2.append(j)
 
    # keep pushing parent of node
    # j till lca is reached
    while y != k:
        path2.append(j / 2)
        j = j // 2
        y -= 1
     
    # printing path from node i to lca
    for l in range(0, len(path1)):
        print(path1[l], end=" ")
 
    # printing path from lca to node j
    for l in range(len(path2) - 2, -1, -1):
        print(path2[l], end=" ")
    print()
 
# Returns the shortest distance
# between nodes labelled as i and j
def ShortestDistance(i, j):
 
    # vector to store binary form of i and j
    v1, v2 = [], []
 
    # finding binary form of i and j
    p1, p2 = i, j
    while i != 0:
        v1.append(i % 2)
        i = i // 2
     
    while j != 0:
        v2.append(j % 2)
        j = j // 2
     
    # as binary form will be in reverse
    # order reverse the vectors
    v1 = v1[::-1]
    v2 = v2[::-1]
 
    # finding the k that is lca (i, j)
    m, n, k = len(v1), len(v2), 0
    if m < n:
        while k < m and v1[k] == v2[k]:
            k += 1
     
    else:
        while k < n and v1[k] == v2[k]:
            k += 1
     
    ShortestPath(p1, p2, k - 1, m, n)
    return m + n - 2 * k
 
# Driver Code
if __name__ == "__main__":
 
    print(ShortestDistance(1, 2))
    print(ShortestDistance(4, 3))
 
# This code is contributed by Rituraj Jain


C#
// C#  representation of finding shortest
// distance between node i and j
using System;
using System.Collections.Generic;   
     
class GFG
{
      
// prints the path between node i and node j
static void ShortestPath(int i, int j, int k, int m,
                                    int n)
{
    // path1 stores path of node i to lca and
    // path2 stores path of node j to lca
    List path1=new List(),
                    path2=new List();
    int x = m - 1;
  
    // push node i in path1
    path1.Add(i);
  
    // keep pushing parent of node labelled
    // as i to path1 until lca is reached
    while (x != k)
    {
        path1.Add(i / 2);
        i = i / 2;
        x--;
    }
    int y = n - 1;
  
    // push node j to path2
    path2.Add(j);
  
    // keep pushing parent of node j till
    // lca is reached
    while (y != k)
    {
        path2.Add(j / 2);
        j = j / 2;
        y--;
    }
  
    // printing path from node i to lca
    for (int l = 0; l < path1.Count; l++)
        Console.Write( path1[l] + " ");
  
    // printing path from lca to node j
    for (int l = path2.Count - 2; l >= 0; l--)
        Console.Write( path2[l] + " ");
    Console.WriteLine();
}
  
// returns the shortest distance between
// nodes labelled as i and j
static int ShortestDistance(int i, int j)
{
    // vector to store binary form of i and j
    List v1=new List(),
                    v2=new List();
  
    // finding binary form of i and j
    int p1 = i;
    int p2 = j;
    while (i != 0)
    {
        v1.Add(i % 2);
        i = i / 2;
    }
    while (j != 0)
    {
        v2.Add(j % 2);
        j = j / 2;
    }
  
    // as binary form will be in reverse order
    // reverse the vectors
    v1.Reverse();
    v2.Reverse();
  
    // finding the k that is lca (i, j)
    int m =v1.Count, n =v2.Count, k = 0;
    if (m < n)
    {
        while (k < m && v1[k] == v2[k])
            k++;
    }
    else
    {
        while (k < n && v1[k] == v2[k])
            k++;
    }
  
    ShortestPath(p1, p2, k - 1, m, n);
    return m + n - 2 * k;
}
  
// Driver code
public static void Main(String []args)
{
    Console.WriteLine( ShortestDistance(1, 2) );
    Console.WriteLine(ShortestDistance(4, 3) );
}
}
 
// This code is contributed by Princi Singh


Javascript


输出:

1 2
1
4 2 1 3
3