【问题标题】:Given a set of data, check if it is a Binary Search Tree?给定一组数据,检查它是否是二叉搜索树?
【发布时间】:2021-07-16 04:21:09
【问题描述】:

这个问题的详细描述如下: 每行包含两个值xy,表示键为x的节点是键为y的节点的父节点。第一个yx 的左孩子,第二个yx 的右孩子。如果y-1,则x 没有对应的孩子。注意树中所有节点的键是distinctpositive

补充:我的代码已经发现了一些错误:1.数据集中给定的节点可能不是从第一层到底层,也就是说读完一行后,我需要搜索父节点的索引,然后添加子节点。 2isBST() 函数不正确,因为如果 左子树 递归地小于当前节点并且 右子树 递归地大于当前节点,则树是二叉搜索树当前节点。 第一个很容易解决,但我不知道如何解决第二个。

示例输入

4
10 5
10 30
30 20
30 -1

第一行的数字表示下面的行数。 对于每一行,左边的数字代表父母,右边的数字代表孩子。如果正确的数字是-1,则表示没有对应的孩子。

样本输出

YES 2

当答案应该是“否”时,我认为我的代码可以成功通过测试点。但是,对于那些应该是“YES + num”的情况,我的代码会失败。谁能指出我的代码中的错误?

实际上,我不太确定二叉搜索树的准确定义。对于样本输入,我认为它不是完整的二叉树。我需要考虑这棵树的层数吗?

我的想法很简单,我只是读取数据并将它们存储到一个数组中,并使用左孩子的属性存储在索引i 处的值是2 * i,而右孩子是2 * i + 1

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class BST {

    public static int[] readData() throws IOException {
        
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        // get the number of rows
        int n = Integer.parseInt(br.readLine());
        String[] strs;
        int[] res = new int[2 * n];
        for (int i = 1; i < n + 1; i++) {
            strs = br.readLine().trim().split(" ");
            //System.out.println(Arrays.toString(strs));
            
            // read the left and right number of one row resp.
            int parent = Integer.parseInt(strs[0]);
            int child = Integer.parseInt(strs[1]);
            // which means that there is no corresponding child, use 0 to denote null
            if (child == -1) {
                child = 0;
            }
            // read the second line with the same parent
            if (res[i - 1] == parent) {
            // put the child as the right child 
                res[2 * (i - 1) + 1] = child;
            }
            else {
                res[i] = parent;
                res[2 * i] = child;
            }
        }
        br.close();
        return res;
    }
    
    public static boolean isLeaf(int[] data, int index) {
        
        // if the node is null, it is not a leaf
        if (data[index] == 0) return false;
        
        
        if (2 * index < data.length - 1) {
            // the left and right children are both null
            if (data[2 * index] == 0 && data[2 * index + 1] == 0) {
                return true;
            }
            // the left and right children are not both null
            else {
                return false;
            }
        }
        // 2 * index is out of bound
        else {
            return true;
        }
    }
    
    public static int countLeaf(int[] data) {
        int count = 0;
        for (int i = 1; i < data.length; i++) {
            // if the node is a leaf, count it
            if (isLeaf(data, i)) count++;
        }
        return count;
    }
    
    public static boolean checkBSTprop(int[] data, int index) {
        // no child can be found
        if (2 * index >= data.length) {
            return true;
        }
        // no child
        if (data[2 * index] == 0 && data[2 * index + 1] == 0) {
            return true;
        }
        // left child is 0, right child is nonzero
        if (data[2 * index] == 0 && data[2 * index + 1] > data[index]) {
            return true;
        }
        // right child is 0, left child is nonzero
        if (data[2 * index + 1] == 0 && data[2 * index] < data[index]) {
            return true;
        }
        // both children are nonzero
        if (data[2 * index] < data[index] && data[2 * index + 1] > data[index]) {
            return true;
        }
        // none of the conditions are satisfied
        return false;
    }
    
    public static boolean isBST(int[] data) {
        for (int i = 1; i < data.length; i++) {
            if (!checkBSTprop(data, i)) {
                return false;
            }
        }
        return true;
    }
    
    public static void main(String[] args) throws IOException {
        int[] res = readData();
        int num = countLeaf(res);
        
        /*
        System.out.println(Arrays.toString(res));
        System.out.println(countLeaf(res));
        System.out.println(checkBSTprop(res, 1));
        System.out.println(checkBSTprop(res, 2));
        System.out.println(checkBSTprop(res, 3));
        System.out.println(checkBSTprop(res, 6));
        System.out.println(isBST(res));
        */
        
        if (isBST(res)) {
            System.out.println("YES " + num);
        }
        else {
            System.out.println("NO");
        }
        
    }
}

【问题讨论】:

  • BST 实际上的意思是“二叉搜索树”
  • 输入格式没有提供左右的线索。至少缺少一个规范。可能有一个规则,第一个提到的孩子总是被假定为左孩子,第二个是右孩子,并且对于每个节点,保证在输入中都会提到左孩子和右孩子,并且在那个命令。应该澄清这一点。例如,为什么输入没有“5 -1”和“5 -1”?有没有假设如果一个节点是一个叶子,它就永远不会这样列出?
  • @trincot 我刚刚添加了这个问题的详细描述。我认为问题假设如果节点是左孩子,那么不会有像5 -1这样的语句。
  • 预期输出中的数字表示什么(例如YES 2)?节点数?树的深度?输入的顺序是否一致? BST 是否允许重复?
  • @vsfDawg 数字 2 表示叶子节点的数量。没有重复的节点,并且节点的所有值都是正数。

标签: java binary-search-tree


【解决方案1】:

您的方法不会始终如一地奏效,因为:

  • 二叉搜索树不一定是完整的树
  • 不保证输入的顺序是广度优先的
  • 似乎不能保证同一父级的两个子级在输入中紧挨着出现。

因此,您不能使用i 来定义数组中存储节点值的位置,使用2 * (i - 1) + 1 之类的公式,也不能使用res[i - 1] 来检查父节点是否已经出现过。

例如,对于这个有效的 BST,您的程序会回答“否”:

6
3 2
3 -1
2 1
2 -1
1 -1
1 -1

如果我们输入相同的树,没有不必要的1 -1(两次),像这样:

4
3 2
3 -1
2 1
2 -1

...那么有一个越界异常。

其次,在isBST 中将子项的值与其父项进行比较是不够的。即使该比较没问题,您仍然可能有一个无效的 BST,例如这个:

                  4
                /
               1
                 \
                  10

这是无效的,因为该叶的唯一有效(不同)整数值是 2 或 3。因此您需要检查筛选递归树的范围。

一个务实的解决方案是用Node类实例真正构建树,并让isBST成为该类的实例方法,这也考虑到这个范围要求。

【讨论】:

  • 感谢您的回答!我接受了您的建议并使用了Node 类方法。经过一番努力,我终于搞定了,我的代码通过了 OJ 系统测试。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2017-09-28
  • 1970-01-01
  • 2018-05-16
  • 1970-01-01
  • 1970-01-01
  • 2019-04-09
  • 1970-01-01
  • 2018-08-10
相关资源
最近更新 更多