【问题标题】:Function: is this binary search tree "odd balanced"?功能:这棵二叉搜索树是“奇平衡”的吗?
【发布时间】:2015-01-21 20:41:10
【问题描述】:

如果左侧奇数后代的数量 == 右侧奇数后代的数量,则树为“奇平衡”。

public boolean isOddBalanced() {   
    return (isOddBalanced (root) >= 0);
}
private int isOddBalanced (Node x) {
    if (x == null) return 0;
    int ls = isOddBalanced (x.left);
    int rs = isOddBalanced (x.right);
    if (Math.abs (ls - rs) > 0) return -1;
    else return 0;
}

我不知道如何计算和比较每边奇数键的数量。任何见解将不胜感激。

尝试实现@nem 的想法:

public boolean isOddBalanced() {   
    return (isOddBalanced (root, '0') >= 0);
}
private int isOddBalanced (Node x, char side) {
    int count = 0;
    if (x == null) return 0;
    count = isOddBalanced (x.left, 'l');
    count = isOddBalanced (x.right, 'r');
    if (x.key % 2 != 0 && side == 'l') count += 1;
    if (x.key % 2 != 0 && side == 'r') count -= 1;
    if (count != 0) return -1;
    else return 0;
}

【问题讨论】:

  • 奇数后代的数量是指持有奇数值的子节点数吗?

标签: java recursion binary-search-tree


【解决方案1】:

您缺少的是一种通过递归计算奇值节点的方法。

您可以使用包装类来实现这一点(因为 Java 是 pass-by-value):

class OddCounter {
    int count = 0;
}

现在你可以做什么,而不是分别计算左奇值节点或右奇值节点,你可以在每次找到左奇值节点时将 1 加到 count 并从 count 中减去 1每次找到一个正确的奇值节点。 这意味着,如果树是奇平衡的,count 变量将为 0。

您的代码将如下所示:

public boolean isOddBalanced() { 
    OddCounter c = new OddCounter();  
    isOddBalancedHelper(root, c, '0');
    return (c.count == 0);
}

private void isOddBalancedHelper (Node x, OddCounter c, char comingFrom) {
    if (x == null) return;
    isOddBalancedHelper(x.left, c, 'l');  
    isOddBalancedHelper(x.right, c, 'r'); 
    if(x.value % 2 != 0 && comingFrom == 'l') {        // if current node is odd and a left child
        c.count++;
    } else if(x.value % 2 != 0 && comingFrom == 'r') { // if current node is odd and a right child
        c.count--;
    }
}

编辑根据您的评论(不使用任何额外的类或函数)

你可以做的是使用实例变量而不是计数器类:

int oddCount;                       // use an instance variable to count the difference between the amount of left odd-nodes and right odd-nodes

public boolean isOddBalanced() { 
    this.oddCount = 0;              // reset count each time balance is calculated to ensure answer is correct each time (and not just on the first call)
    isOddBalancedHelper(root, '0');
    return (this.oddCount == 0);
}

private void isOddBalancedHelper (Node x, char comingFrom) {
    if (x == null) return;
    isOddBalancedHelper(x.left, 'l');  
    isOddBalancedHelper(x.right, 'r'); 
    if(x.value % 2 != 0 && comingFrom == 'l') {        // if current node is odd and a left child
        this.oddCount++;
    } else if(x.value % 2 != 0 && comingFrom == 'r') { // if current node is odd and a right child
        this.oddCount--;
    }
}

您可以进行的另一项改进是将oddCount 的值兑现,并且仅在树内容以任何方式更改(添加/删除节点,更改节点值)时更新它。

这将允许您对每个树结构仅计算一次 isOddBalanced() 的值。

【讨论】:

  • 不幸的是我不能使用任何其他函数/类。
  • 然后查看我的编辑以寻找可能的解决方案。另外,当您说the number of odd descendents on the left == number of odd descendents on the right 时,这是否适用于树中的每个 节点?也就是说,每个子树是否必须是奇平衡才能使整棵树成为奇平衡?这就是我的回答向您展示的方法。还是仅仅意味着根左侧具有奇值的节点数量必须等于根右侧具有奇值的节点数量?
  • 假设你有一棵完美的二叉树,有 7 个节点,按顺序从“A”到“G”。还假设节点A、B、E 和G 是奇数(即在根节点D 的每一侧有两个奇数节点)。据我追踪您的代码,它将回答以节点D 为根的树是not 奇平衡的——节点A、B 和E 是它们各自的左子节点父节点 (comingFrom == 'l'),因此它们导致计数器递增,而节点 G 是右子节点 (comingFrom == 'r'),因此它递减计数器,因此最终结果为 oddCount == 2。
【解决方案2】:

看看这个。

private int countNode(Node x){
    if(x == null) return 0;
    else return countNode(x.left) + countNode(x.right) + 1;
}

private bool isOddBalanced(Node x){
    int ls = countNode(x.left);
    int rs = countNode(x.right);
    return (ls == rs);
}

【讨论】:

  • 我认为 OP 需要检查每一侧 包含奇数值的节点数是否相等,而不是每一侧的节点数是否相等跨度>
  • 这对我来说很奇怪,我当时不明白:/!
【解决方案3】:

由于您想知道左侧奇数后代的数量==右侧奇数后代的数量,因此您只需要左右孩子之间的差异。

public boolean isOddBalanced() {   
    return (CountChilds(root.left) == CountChilds(root.right));
}
private int CountChilds(Node x) {
    if (x == null) return 0;
    // left childs + right childs + me
    else return CountChilds(x.left) + CountChilds(x.right) + 1; 
}

【讨论】:

  • 基本上和我做的一样......并不是OP想要的。
【解决方案4】:

您的问题似乎不正确。

如果左侧奇数后代的数量 == 右侧奇数后代的数量,则树是“奇平衡”的。

这意味着您需要比较根节点左侧奇数后代的数量与根节点右侧奇数后代的数量。然而,这不是为树定义属性的常用方法——这些属性通常是为树中的每个节点定义的。这意味着您需要检查树的每个节点中的奇数余额。

就像@nem 所说的那样,您可以在遍历整个树的单个递归过程中做到这一点。但是,您可以稍微改进一下解决方案。

请注意,一旦我们将奇平衡定义为递归属性,那么如果它的任何子树不平衡,则该树将不是奇平衡。因此,在重复出现时,我们可以同时检索关于奇数节点数量的信息和。如果没有两个结果的复合容器,我们怎么能做到这一点?好吧,如果一个子树不平衡,整棵树也不平衡,对吧?所以我们已经知道整棵树是不平衡的,因此不需要关于节点数量的信息。因此,我们可以将这些互斥的信息片段作为单个 int 值返回:奇平衡子树中奇数节点的数量为零或正数,或者对于不平衡子树为负数。

private int isOddBalanced (Node x) {
    // empty tree is balanced and it contains no odd nodes
    if (x == null) return 0;

    // check subtrees; if any is unbalanced, return the status up the tree
    int ls = isOddBalanced (x.left);
    // don't test the right subtree if the left one is unbalanced
    if (ls < 0) return -1;

    int rs = isOddBalanced (x.right);
    if (rs < 0) return -1;

    // when both are balanced test for odd-nodes numbers equality
    if (ls != rs) return -1;

    // return the current sub-total
    return ls + rs + ((x.key % 2 == 0) ? 0 : 1);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多