数组中两个节点之间的最短路径,如二叉树的表示
考虑一棵二叉树,其中每个节点都有两个子节点,除了叶节点。如果一个节点被标记为“v”,那么它的右孩子将被标记为 2v+1,而左孩子将被标记为 2v。根标记为
给定两个标记为 i 和 j 的节点,任务是找到最短距离和从 i 到 j 的路径。并从根节点打印节点 i 和节点 j 的路径。
例子:
Input : i = 1, j = 2
Output : 1
Explanation:
Path is 1 2
Input: i = 4, j = 3
Output : 3
Explanation:
Path is 4 2 1 3
这个问题主要是二叉树的两个给定键之间的查找距离的扩展。在这里,我们不仅找到了最短距离,还找到了路径。
两个节点 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_2 [/特克斯]… 并且节点 j 的二进制表示为 n 长度 [特克斯]j_2 [/特克斯]…… .
因此,我们从根知道 i 和 j 的路径。找出 k 使得对于所有 p<=k = .这是二进制形式的 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