📜  通过二叉树中的链表查找从根开始的路径方向

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

通过二叉树中的链表查找从根开始的路径方向

给定二叉树T的根和链表L ,任务是找到从根开始的路径方向,使得存在从根到树的任何叶节点的路径,使得值是该路径形成链接列表。如果不存在任何这样的路径,则打印“-1”

注:左方向的路径用L表示,右方向的路径用R表示。

例子

方法:给定的问题可以通过同时遍历二叉树和链表来解决,如果当前节点与链表的当前节点不匹配,则该路径不正确。否则,检查有效路径的其他顺序。请按照以下步骤解决给定的问题:

  • 声明一个函数,比如findPath(root, head, path)并在这个函数中执行以下步骤:
    • 如果 root 为NULL或 root 的值与 head 的节点值不同,则返回false
    • 如果当前根节点是叶子节点并且头是最后一个节点,则返回true
    • 在向量path[]中插入字符'L'并递归调用左子树为findPath(root->left, head->next, path)如果此函数返回的值为true ,则存在路径并从函数返回true 。否则,从向量path[]中弹出最后一个字符。
    • 在向量path[]中插入字符'R'并递归调用右子树为findPath(root->right, head->next, path)如果此函数返回的值为true ,则存在路径并从函数返回true 。否则,从向量path[]中弹出最后一个字符。
    • 否则,从函数返回false
  • 如果在给定的二叉树中找到链表,则初始化一个向量,例如存储方向的路径 []
  • 调用函数findPath(root, head, path)
  • 如果向量路径的大小为0 ,则打印“-1” 。否则,打印存储在向量path[]中的路径。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
struct ListNode {
    int data;
    ListNode* next;
    ListNode(int data)
    {
        this->data = data;
        this->next = NULL;
    }
};
 
struct TreeNode {
    TreeNode* left;
    TreeNode* right;
    int val;
 
    TreeNode(int x)
        : left(NULL), right(NULL), val(x)
    {
    }
};
 
// Function to create the Linked list
ListNode* makeList(int arr[], int n)
{
    ListNode* h = NULL;
    ListNode* root;
    for (int i = 0; i < n; i++) {
        int data = arr[i];
        ListNode* node = new ListNode(data);
 
        if (h == NULL) {
            h = node;
            root = h;
        }
        else {
            root->next = node;
            root = node;
        }
    }
    return h;
}
 
// utility function to build tree
// from its level order traversal
TreeNode* build_tree(int nodes[], int n)
{
    TreeNode* root = new TreeNode(nodes[0]);
    queue q;
    bool is_left = true;
    TreeNode* cur = NULL;
    q.push(root);
 
    for (int i = 1; i < n; i++) {
        TreeNode* node = NULL;
        if (nodes[i] != '#') {
            node = new TreeNode(nodes[i]);
            q.push(node);
        }
 
        if (is_left) {
            cur = q.front();
            q.pop();
            cur->left = node;
            is_left = false;
        }
        else {
            cur->right = node;
            is_left = true;
        }
    }
 
    return root;
}
 
// Function to find path of linked list
// in binary tree, by traversing the
// tree in pre-order fashion
bool findPath(TreeNode* root, ListNode* head,
              vector& path)
{
    // Base Case
    if (root == NULL) {
        return false;
    }
 
    // If current tree node is not same
    // as the current LL Node, then
    // return False
    if (root->val != head->data)
        return false;
 
    // Complete the path of LL is traced
    if (root->left == NULL
        and root->right == NULL
        and head->next == NULL) {
        return true;
    }
 
    // First go to left
    path.push_back('L');
 
    // If path found in left subtree
    if (findPath(root->left,
                 head->next, path))
        return true;
 
    // Pop L because valid path is
    // not traced
    path.pop_back();
 
    // Go to right
    path.push_back('R');
 
    // If path found in right subtree
    if (findPath(root->right,
                 head->next, path))
        return true;
 
    // Pop R because valid path
    // is not traced
    path.pop_back();
 
    return false;
}
 
// Function to find the valid path
void find(TreeNode* root, ListNode* head)
{
    vector path;
 
    // Function call to find the direction
    // of the LL path
    findPath(root, head, path);
 
    // If there doesn't exists any
    // such paths
    if (path.size() == 0) {
        cout << "-1";
        return;
    }
 
    // Print the path
    for (int i = 0;
         i < path.size(); i++) {
        cout << path[i] << " ";
    }
}
 
// Driver Code
int main()
{
    int tree[] = { 1, 2, 3, 4, 5, 6,
                   8, -1, -1, 8 };
    TreeNode* root = build_tree(tree, 10);
 
    int ll[] = { 1, 2, 5, 8 };
    ListNode* head = makeList(ll, 4);
 
    find(root, head);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
 
static class ListNode {
    int data;
    ListNode next;
    ListNode(int data)
    {
        this.data = data;
        this.next = null;
    }
};
 
static class TreeNode {
    TreeNode left;
    TreeNode right;
    int val;
 
    TreeNode(int x){
        left = null;
        right = null;
        val = x;   
    }
};
 
// Function to create the Linked list
static ListNode makeList(int arr[], int n)
{
    ListNode h = null;
    ListNode root = new ListNode(0);
    for (int i = 0; i < n; i++) {
        int data = arr[i];
        ListNode node = new ListNode(data);
 
        if (h == null) {
            h = node;
            root = h;
        }
        else {
            root.next = node;
            root = node;
        }
    }
    return h;
}
 
// utility function to build tree
// from its level order traversal
static TreeNode build_tree(int nodes[], int n)
{
    TreeNode root = new TreeNode(nodes[0]);
    Queue q = new LinkedList<>();
    boolean is_left = true;
    TreeNode cur = null;
    q.add(root);
 
    for (int i = 1; i < n; i++) {
        TreeNode node = null;
        if (nodes[i] != 0) {
            node = new TreeNode(nodes[i]);
            q.add(node);
        }
 
        if (is_left) {
            cur = q.peek();
            q.remove();
            cur.left = node;
            is_left = false;
        }
        else {
            cur.right = node;
            is_left = true;
        }
    }
 
    return root;
}
 
// Function to find path of linked list
// in binary tree, by traversing the
// tree in pre-order fashion
static boolean findPath(TreeNode root, ListNode head,
              Vector path)
{
    // Base Case
    if (root == null) {
        return false;
    }
 
    // If current tree node is not same
    // as the current LL Node, then
    // return False
    if (root.val != head.data)
        return false;
 
    // Complete the path of LL is traced
    if (root.left == null
        && root.right == null
        && head.next == null) {
        return true;
    }
 
    // First go to left
    path.add('L');
 
    // If path found in left subtree
    if (findPath(root.left,
                 head.next, path))
        return true;
 
    // Pop L because valid path is
    // not traced
    path.remove(path.size()-1);
 
    // Go to right
    path.add('R');
 
    // If path found in right subtree
    if (findPath(root.right,
                 head.next, path))
        return true;
 
    // Pop R because valid path
    // is not traced
    path.remove(path.size()-1);
 
    return false;
}
 
// Function to find the valid path
static void find(TreeNode root, ListNode head)
{
    Vector path = new Vector();
 
    // Function call to find the direction
    // of the LL path
    findPath(root, head, path);
 
    // If there doesn't exists any
    // such paths
    if (path.size() == 0) {
        System.out.print("-1");
        return;
    }
 
    // Print the path
    for (int i = 0;
         i < path.size(); i++) {
        System.out.print(path.get(i)+ " ");
    }
}
 
// Driver Code
public static void main(String[] args)
{
    int tree[] = { 1, 2, 3, 4, 5, 6,
                   8, -1, -1, 8 };
    TreeNode root = build_tree(tree, 10);
 
    int ll[] = { 1, 2, 5, 8 };
    ListNode head = makeList(ll, 4);
 
    find(root, head);
 
}
}
 
// This code is contributed by 29AjayKumar


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
public class GFG{
 
class ListNode {
    public int data;
    public ListNode next;
    public ListNode(int data)
    {
        this.data = data;
        this.next = null;
    }
};
 
class TreeNode {
    public TreeNode left;
    public TreeNode right;
    public int val;
 
    public TreeNode(int x){
        left = null;
        right = null;
        val = x;   
    }
};
 
// Function to create the Linked list
static ListNode makeList(int []arr, int n)
{
    ListNode h = null;
    ListNode root = new ListNode(0);
    for (int i = 0; i < n; i++) {
        int data = arr[i];
        ListNode node = new ListNode(data);
 
        if (h == null) {
            h = node;
            root = h;
        }
        else {
            root.next = node;
            root = node;
        }
    }
    return h;
}
 
// utility function to build tree
// from its level order traversal
static TreeNode build_tree(int []nodes, int n)
{
    TreeNode root = new TreeNode(nodes[0]);
    Queue q = new Queue();
    bool is_left = true;
    TreeNode cur = null;
    q.Enqueue(root);
 
    for (int i = 1; i < n; i++) {
        TreeNode node = null;
        if (nodes[i] != 0) {
            node = new TreeNode(nodes[i]);
            q.Enqueue(node);
        }
 
        if (is_left) {
            cur = q.Peek();
            q.Dequeue();
            cur.left = node;
            is_left = false;
        }
        else {
            cur.right = node;
            is_left = true;
        }
    }
 
    return root;
}
 
// Function to find path of linked list
// in binary tree, by traversing the
// tree in pre-order fashion
static bool findPath(TreeNode root, ListNode head,
              List path)
{
   
    // Base Case
    if (root == null) {
        return false;
    }
 
    // If current tree node is not same
    // as the current LL Node, then
    // return False
    if (root.val != head.data)
        return false;
 
    // Complete the path of LL is traced
    if (root.left == null
        && root.right == null
        && head.next == null) {
        return true;
    }
 
    // First go to left
    path.Add('L');
 
    // If path found in left subtree
    if (findPath(root.left,
                 head.next, path))
        return true;
 
    // Pop L because valid path is
    // not traced
    path.RemoveAt(path.Count-1);
 
    // Go to right
    path.Add('R');
 
    // If path found in right subtree
    if (findPath(root.right,
                 head.next, path))
        return true;
 
    // Pop R because valid path
    // is not traced
    path.RemoveAt(path.Count-1);
 
    return false;
}
 
// Function to find the valid path
static void find(TreeNode root, ListNode head)
{
    List path = new List();
 
    // Function call to find the direction
    // of the LL path
    findPath(root, head, path);
 
    // If there doesn't exists any
    // such paths
    if (path.Count == 0) {
        Console.Write("-1");
        return;
    }
 
    // Print the path
    for (int i = 0;
         i < path.Count; i++) {
        Console.Write(path[i]+ " ");
    }
}
 
// Driver Code
public static void Main(String[] args)
{
    int []tree = { 1, 2, 3, 4, 5, 6,
                   8, -1, -1, 8 };
    TreeNode root = build_tree(tree, 10);
 
    int []ll = { 1, 2, 5, 8 };
    ListNode head = makeList(ll, 4);
 
    find(root, head);
 
}
}
 
// This code is contributed by 29AjayKumar



输出:
L R L

时间复杂度: O(N + M),其中 N 是二叉树中的节点数,M 是Linked List 的长度
辅助空间: O(H),其中 H 是二叉树的高度