给定一个由不同节点和一对节点组成的二叉树。任务是在二叉树中找到并打印两个给定节点之间的路径。
例子:
Input: N1 = 7, N2 = 4
Output: 7 3 1 4
方法:本文讨论了一种解决此问题的方法。在本文中,将讨论甚至优化的递归方法。
在这种递归方法中,以下是步骤:
- 递归查找第一个值,找到后将其添加到堆栈中。
- 现在,无论是在回溯还是正向跟踪中访问的每个节点,都将值添加到堆栈中,但是如果在正向跟踪中添加了该节点,则在回溯中将其删除,并继续进行此操作,直到找到第二个值或所有节点都被访问为止。
例如:考虑在上面的树中找到7到9之间的路径。我们将树作为DFS遍历,一旦找到值7,就将其添加到堆栈中。遍历路径0-> 1-> 3-> 7。
现在,在回溯的同时,将3和1添加到堆栈中。因此,到目前为止,堆栈具有[7,3,1],子级1具有正确的子级,因此我们首先将其添加到堆栈中。现在,堆栈包含[7、3、1、4]。访问4的左孩子,将其添加到堆栈中。堆栈现在包含[7、3、1、4、8]。由于没有其他节点,我们将返回到上一个节点,并且由于已经将8添加到堆栈中,因此将其删除。现在节点4有一个合适的子节点,我们将其添加到堆栈中,因为这是我们一直在寻找的第二个值,因此不会再进行任何递归调用。最后,堆栈包含[7、3、1、4、9]。
下面是上述方法的实现:
C++
// CPP implementation of the approach
#include
using namespace std;
// A binary tree node
class Node {
public:
int value;
Node *left, *right;
Node(int value) {
this->value = value;
left = NULL;
right = NULL;
}
};
bool firstValueFound = false;
bool secondValueFound = false;
stack stk;
Node *root = NULL;
// Function to find the path between
// two nodes in binary tree
void pathBetweenNode(Node *root, int v1, int v2) {
// Base condition
if (root == NULL) return;
// If both the values are found then return
if (firstValueFound && secondValueFound) return;
// Starting the stack frame with
// isAddedToStack = false flag
bool isAddedToStack = false;
// If one of the value is found then add the
// value to the stack and make the isAddedToStack = true
if (firstValueFound ^ secondValueFound) {
stk.push(root);
isAddedToStack = true;
}
// If none of the two values is found
if (!(firstValueFound && secondValueFound)) {
pathBetweenNode(root->left, v1, v2);
}
// Ccopy of current state of firstValueFound
// and secondValueFound flag
bool localFirstValueFound = firstValueFound;
bool localSecondValueFound = secondValueFound;
// If the first value is found
if (root->value == v1) firstValueFound = true;
// If the second value is found
if (root->value == v2) secondValueFound = true;
bool localAdded = false;
// If one of the value is found and the value
// was not added to the stack yet or there was
// only one value found and now both the values
// are found and was not added to
// the stack then add it
if (((firstValueFound ^ secondValueFound) ||
((localFirstValueFound ^ localSecondValueFound) &&
(firstValueFound && secondValueFound))) &&
!isAddedToStack) {
localAdded = true;
stk.push(root);
}
// If none of the two values is found yet
if (!(firstValueFound && secondValueFound)) {
pathBetweenNode(root->right, v1, v2);
}
if ((firstValueFound ^ secondValueFound) && !isAddedToStack && !localAdded)
stk.push(root);
if ((firstValueFound ^ secondValueFound) && isAddedToStack) stk.pop();
}
// Function to find the path between
// two nodes in binary tree
stack pathBetweenNode(int v1, int v2)
{
// Global root
pathBetweenNode(::root, v1, v2);
// If both the values are found
// then return the stack
if (firstValueFound && secondValueFound)
{
// Global Stack Object
return ::stk;
}
// If none of the two values is
// found then return empty stack
stack stk;
return stk;
}
// Recursive function to print the
// contents of a stack in reverse
void print(stack stk)
{
// If the stack is empty
if (stk.empty()) return;
// Get the top value
int value = stk.top()->value;
stk.pop();
// Recursive call
print(stk);
// Print the popped value
cout << value << " ";
}
// Driver code
int main(int argc, char const *argv[])
{
root = new Node(0);
root->left = new Node(1);
root->right = new Node(2);
root->left->left = new Node(3);
root->left->right = new Node(4);
root->right->left = new Node(5);
root->right->right = new Node(6);
root->left->left->left = new Node(7);
root->left->right->left = new Node(8);
root->left->right->right = new Node(9);
// Find and print the path
stack stck = pathBetweenNode(7, 4);
print(stck);
}
// This code is contributed by sanjeev2552
Java
// Java implementation of the approach
import java.util.Stack;
public class GFG {
// A binary tree node
private static class Node {
public Node left;
public int value;
public Node right;
public Node(int value)
{
this.value = value;
left = null;
right = null;
}
}
private boolean firstValueFound = false;
private boolean secondValueFound = false;
private Stack stack = new Stack();
private Node root = null;
public GFG(Node root)
{
this.root = root;
}
// Function to find the path between
// two nodes in binary tree
public Stack pathBetweenNode(int v1, int v2)
{
pathBetweenNode(this.root, v1, v2);
// If both the values are found
// then return the stack
if (firstValueFound && secondValueFound) {
return stack;
}
// If none of the two values is
// found then return empty stack
return new Stack();
}
// Function to find the path between
// two nodes in binary tree
private void pathBetweenNode(Node root, int v1, int v2)
{
// Base condition
if (root == null)
return;
// If both the values are found then return
if (firstValueFound && secondValueFound)
return;
// Starting the stack frame with
// isAddedToStack = false flag
boolean isAddedToStack = false;
// If one of the value is found then add the
// value to the stack and make the isAddedToStack = true
if (firstValueFound ^ secondValueFound) {
stack.add(root);
isAddedToStack = true;
}
// If none of the two values is found
if (!(firstValueFound && secondValueFound)) {
pathBetweenNode(root.left, v1, v2);
}
// Ccopy of current state of firstValueFound
// and secondValueFound flag
boolean localFirstValueFound = firstValueFound;
boolean localSecondValueFound = secondValueFound;
// If the first value is found
if (root.value == v1)
firstValueFound = true;
// If the second value is found
if (root.value == v2)
secondValueFound = true;
boolean localAdded = false;
// If one of the value is found and the value
// was not added to the stack yet or there was
// only one value found and now both the values
// are found and was not added to
// the stack then add it
if (((firstValueFound ^ secondValueFound)
|| ((localFirstValueFound ^ localSecondValueFound)
&& (firstValueFound && secondValueFound)))
&& !isAddedToStack) {
localAdded = true;
stack.add(root);
}
// If none of the two values is found yet
if (!(firstValueFound && secondValueFound)) {
pathBetweenNode(root.right, v1, v2);
}
if ((firstValueFound ^ secondValueFound)
&& !isAddedToStack && !localAdded)
stack.add(root);
if ((firstValueFound ^ secondValueFound)
&& isAddedToStack)
stack.pop();
}
// Recursive function to print the
// contents of a stack in reverse
private static void print(Stack stack)
{
// If the stack is empty
if (stack.isEmpty())
return;
// Get the top value
int value = stack.pop().value;
// Recursive call
print(stack);
// Print the popped value
System.out.print(value + " ");
}
// Driver code
public static void main(String[] args)
{
Node root = new Node(0);
root.left = new Node(1);
root.right = new Node(2);
root.left.left = new Node(3);
root.left.right = new Node(4);
root.right.left = new Node(5);
root.right.right = new Node(6);
root.left.left.left = new Node(7);
root.left.right.left = new Node(8);
root.left.right.right = new Node(9);
// Find and print the path
GFG pathBetweenNodes = new GFG(root);
Stack stack
= pathBetweenNodes.pathBetweenNode(7, 4);
print(stack);
}
}
Python3
# Python3 implementation of
# the above approach
# A binary tree node
class Node:
def __init__(self, value):
self.left = None
self.right = None
self.value = value
firstValueFound = False
secondValueFound = False
stack = []
root = None
# Function to find the path
# between two nodes in binary
# tree
def pathBetweennode(v1, v2):
global firstValueFound, secondValueFound
pathBetweenNode(root, v1, v2)
# If both the values are found
# then return the stack
if (firstValueFound and
secondValueFound):
return stack
# If none of the two values is
# found then return empty stack
return []
# Function to find the path
# between two nodes in binary
# tree
def pathBetweenNode(root,
v1, v2):
global firstValueFound, secondValueFound
# Base condition
if (root == None):
return
# If both the values are found
# then return
if (firstValueFound and
secondValueFound):
return
# Starting the stack frame with
# isAddedToStack = false flag
isAddedToStack = False
# If one of the value is found
# then add the value to the
# stack and make the isAddedToStack = true
if (firstValueFound ^ secondValueFound):
stack.append(root)
isAddedToStack = True
# If none of the two values
# is found
if (not (firstValueFound and
secondValueFound)):
pathBetweenNode(root.left,
v1, v2)
# Ccopy of current state of
# firstValueFound and
# secondValueFound flag
localFirstValueFound = firstValueFound
localSecondValueFound = secondValueFound
# If the first value is found
if (root.value == v1):
firstValueFound = True
# If the second value is found
if (root.value == v2):
secondValueFound = True
localAdded = False
# If one of the value is found
# and the value was not added
# to the stack yet or there was
# only one value found and now
# both the values are found and
# was not added to the stack
# then add it
if (((firstValueFound ^
secondValueFound) or
((localFirstValueFound ^
localSecondValueFound) and
(firstValueFound and
secondValueFound))) and
not isAddedToStack):
localAdded = True
stack.append(root)
# If none of the two values
# is found yet
if (not (firstValueFound and
secondValueFound)):
pathBetweenNode(root.right,
v1, v2)
if ((firstValueFound ^
secondValueFound) and
not isAddedToStack and
not localAdded):
stack.append(root)
if ((firstValueFound ^
secondValueFound) and
isAddedToStack):
stack.pop()
# Recursive function to print
# the contents of a stack in
# reverse
def pri(stack):
# If the stack is empty
if (len(stack) == 0):
return
# Get the top value
value = stack.pop().value
# Recursive call
pri(stack)
# Print the popped value
print(value, end = " ")
# Driver code
if __name__ == "__main__":
root = Node(0)
root.left = Node(1)
root.right = Node(2)
root.left.left = Node(3)
root.left.right = Node(4)
root.right.left = Node(5)
root.right.right = Node(6)
root.left.left.left = Node(7)
root.left.right.left = Node(8)
root.left.right.right = Node(9)
# Find and print the path
stack = pathBetweennode(7, 4)
pri(stack)
# This code is contributed by Rutvik_56
C#
// C# implementation of the approach
using System;
using System.Collections;
using System.Collections.Generic;
class GFG
{
// A binary tree node
public class Node
{
public Node left;
public int value;
public Node right;
public Node(int value)
{
this.value = value;
left = null;
right = null;
}
}
private Boolean firstValueFound = false;
private Boolean secondValueFound = false;
private Stack stack = new Stack();
private Node root = null;
public GFG(Node root)
{
this.root = root;
}
// Function to find the path between
// two nodes in binary tree
public Stack pathBetweenNode(int v1, int v2)
{
pathBetweenNode(this.root, v1, v2);
// If both the values are found
// then return the stack
if (firstValueFound && secondValueFound)
{
return stack;
}
// If none of the two values is
// found then return empty stack
return new Stack();
}
// Function to find the path between
// two nodes in binary tree
private void pathBetweenNode(Node root, int v1, int v2)
{
// Base condition
if (root == null)
return;
// If both the values are found then return
if (firstValueFound && secondValueFound)
return;
// Starting the stack frame with
// isAddedToStack = false flag
Boolean isAddedToStack = false;
// If one of the value is found then add the
// value to the stack and make the isAddedToStack = true
if (firstValueFound ^ secondValueFound)
{
stack.Push(root);
isAddedToStack = true;
}
// If none of the two values is found
if (!(firstValueFound && secondValueFound))
{
pathBetweenNode(root.left, v1, v2);
}
// Ccopy of current state of firstValueFound
// and secondValueFound flag
Boolean localFirstValueFound = firstValueFound;
Boolean localSecondValueFound = secondValueFound;
// If the first value is found
if (root.value == v1)
firstValueFound = true;
// If the second value is found
if (root.value == v2)
secondValueFound = true;
Boolean localAdded = false;
// If one of the value is found and the value
// was not added to the stack yet or there was
// only one value found and now both the values
// are found and was not added to
// the stack then add it
if (((firstValueFound ^ secondValueFound)
|| ((localFirstValueFound ^ localSecondValueFound)
&& (firstValueFound && secondValueFound)))
&& !isAddedToStack)
{
localAdded = true;
stack.Push(root);
}
// If none of the two values is found yet
if (!(firstValueFound && secondValueFound))
{
pathBetweenNode(root.right, v1, v2);
}
if ((firstValueFound ^ secondValueFound)
&& !isAddedToStack && !localAdded)
stack.Push(root);
if ((firstValueFound ^ secondValueFound)
&& isAddedToStack)
stack.Pop();
}
// Recursive function to print the
// contents of a stack in reverse
private static void print(Stack stack)
{
// If the stack is empty
if (stack.Count==0)
return;
// Get the top value
int value = stack.Pop().value;
// Recursive call
print(stack);
// Print the Popped value
Console.Write(value + " ");
}
// Driver code
public static void Main(String []args)
{
Node root = new Node(0);
root.left = new Node(1);
root.right = new Node(2);
root.left.left = new Node(3);
root.left.right = new Node(4);
root.right.left = new Node(5);
root.right.right = new Node(6);
root.left.left.left = new Node(7);
root.left.right.left = new Node(8);
root.left.right.right = new Node(9);
// Find and print the path
GFG pathBetweenNodes = new GFG(root);
Stack stack
= pathBetweenNodes.pathBetweenNode(7, 4);
print(stack);
}
}
// This code is contributed by Arnab Kundu
输出:
7 3 1 4