简体   繁体   English

如何识别二叉搜索树的叶节点

[英]How to identify the leaf nodes of a binary search tree

I recently came across the following problem that was said to have been asked in a technical interview: 我最近遇到了一个据说在技术面试中被问过的问题:

Given the preorder traversal of a binary search tree, how do we identify the leaf nodes without building the tree? 给定二叉搜索树的前序遍历,我们如何在不构建树的情况下识别叶节点?

Eg: [5,3,2,4,8,7,9] 例如:[5,3,2,4,8,7,9]

The question was left vague by whoever posted it and given the vagueness, I'm not really sure what the approach should be for this one and I haven't been able to find verified solutions online. 任何人发布它并且模糊不清,问题都是模糊的,我不确定这个方法应该是什么,我无法在网上找到经过验证的解决方案。

How should this problem be solved? 该问题应如何解决?

Consider your example : [5,3,2,4,8,7,9] 考虑你的例子: [5,3,2,4,8,7,9]

Take the first element : 5 . 拿第一个元素: 5

Since this is a preorder traversal that's root node for sure. 因为这是一个前序遍历 ,它确实是根节点

Now, in preorder traversal, after root u recur for left subtree and then right subtree . 现在,在前序遍历中,在root之后重复左子树然后右子树

And u also know that in BST : 你也知道在BST

 nodes in left subtree < root < nodes in right subtree 

Hence after 5, all the elements in series which are less than 5 belongs to left subtree . 因此,在5之后,所有小于5的系列元素属于左子树 And similarly for right. 同样对于正确的。

So u end up having this (you don't need to explicitly create tree) : 所以你最终得到了这个(你不需要显式创建树)

        5
     /    \
  [3,2,4] [8,7,9]

Now [3,2,4] is preorder traversal for left subtree part and [8,7,9] for right. 现在[3,2,4]是左子树部分的前序遍历,右边是[8,7,9]

Recurse for both sub-arrays and the moment u are left with array of size 1, that's the leaf. 递归两个子阵列,当你留下大小为1的数组时,那就是叶子。

I assume we consider only perfect BSTs. 我假设我们只考虑完美的 BST。 Because if it is not perfect, there can be (possibly) multiple answers. 因为如果不完美,可能会有(可能)多个答案。

So looking at the examples and description of preorder traversal it is obvious that roots are taken first and then it 'does down' to leaves. 因此,查看前序遍历的示例和描述很明显,首先采用根,然后将其“下降”到叶子。 As we have a perfect tree then we can see that leaves are always going in pairs. 因为我们有一棵完美的树,所以我们可以看到树叶总是成对出现。 And also we need to 'skip' their parents. 我们还需要“跳过”他们的父母。

Intuitively I would suggest going backwards, as 2 last elements are leaves ('*' denotes not leaves): 直觉上我建议倒退,因为最后两个元素是叶子('*'表示不是叶子):

[*,*,2,4,*,7,9] <-- The overal procedure is as follows (going backwards): [*,*,2,4,*,7,9] < - 整个程序如下(向后):

  1. take 2 leaves; 拿2片叶子;
  2. skip 1 node (their parent); 跳过1个节点(他们的父节点);
  3. repeat steps [1-2]; 重复步骤[1-2];
  4. skip 1 more node (parent of parents); 跳过1个节点(父节点的父节点);
  5. done (there is no more elements left). 完成(没有剩余的元素)。

Now demo on a larger array (15 elements, again perfect tree): 现在演示一个更大的阵列(15个元素,再次完美的树):

[*,*,*,l,l,*,l,l,*,*,l,l,*,l,l] <-- where l denotes a leaf. [*,*,*,l,l,*,l,l,*,*,l,l,*,l,l] < - 其中l表示叶子。 Steps (also backwards): 步骤(也向后):

  1. 1-4 from prevoius example; 从prevoius例子1-4;
  2. again 1-4 from previous example; 从前面的例子再次1-4;
  3. skip 1 more node (parent of parents of parents); 跳过1个节点(父母的父母);
  4. done (no more elements). 完成(没有更多元素)。

Hope, you got an idea. 希望,你有个主意。

As for programmatical approach, you can spot a repeating pattern in above intuitive approach and use a recursion depending on the height of the tree (can be easilly computed as log2(n+1) where n is number of elements in tree, also look wiki ) but probably starting from the beginning of the array. 至于编程方法,你可以在上面的直观方法中发现重复模式,并根据树的高度使用递归(可以简单计算为log2(n+1) ,其中n是树中元素的数量,也看维基 )但可能从数组的开头开始。 Pseudocode: 伪代码:

void getLeaves(int height) {
    if (height == 2) {       // there is only a parent and two childs (leaves)
        skip(1);             // skip 1 element
        take(2);             // next two are leaves, get them
    }
    else {
        skip(1);             // skip parent of parents (of parents ...)
        getLeaves(height-1); // call on left part of array
        getLeaves(height-1); // call on right part of array
    }
}
import java.util.ArrayList;

public class PreorderArrayToTree {

    static void printLeafNodes(ArrayList<Integer> list) {
        if(list.size()==0)return;
        if(list.size()==1) {
            System.out.print(list.get(0)+" ");
            return;
        }
        int parent = list.get(0);
        ArrayList<Integer> leftChild = new ArrayList<Integer>();
        ArrayList<Integer> rightChild =  new ArrayList<Integer>();
        for(int i=1; i<list.size(); i++) {
            if(list.get(i)<parent)leftChild.add(list.get(i));
            if(list.get(i)>parent)rightChild.add(list.get(i));
        };
        printLeafNodes(leftChild);
        printLeafNodes(rightChild);
    };

    public static void main(String[] args) {
        //int[] arr  = {10,5,1,7,40,50};
        //int[] arr =  {890, 325, 290, 530, 965};
        int[] arr = {3,2,4};
        ArrayList<Integer> list = new ArrayList<Integer>();
        for(int i=0; i<arr.length; i++)list.add(arr[i]);
        printLeafNodes(list);
    };
};
void printleafnode(int*arr, int size)
{
    int i = 0;

    while(i < size)
    {
        if(arr[i] > arr[i+1])
            i= i+1;
        else
        {
            if(arr[i] < arr[i+1])
            {
                printf(" %d " ,arr[i]);
                i= i+1;
            }
         }
    }
    printf(" %d ", arr[i]);
    printf("\n");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM