用大于或等于节点的节点总和替换BST节点

时间:2013-04-27 17:51:06

标签: algorithm data-structures tree

我想知道以下问题的算法:
“给定BST(可能存在重复节点),将每个节点替换为值,该值是所有节点的值大于等于当前节点的值。”

示例:

  
                              5                15
                            2  10     o/p:   17  10
  

我通过反向有序遍历来保持变量'sum'。这是代码:
---------------------------------------------- -------------------------------------------------- -------

  
    


// sum是单个元素数组。最初总和[0] = 0
        public static void replaceNodeValue(BSTNode root,int [] sum){
        if(root == null)返回;
        replaceNodeValue(root.right,sum);
        root.data =(sum [0] = sum [0] + root.data);
        replaceNodeValue(root.left,sum);     
}

  

问题是此代码仅在树不包含重复节点时才有效。我正在寻找能够处理重复节点的正确算法。

代码失败的一种情况是:

  
                               5
                            5     5
  

请帮忙。 感谢

6 个答案:

答案 0 :(得分:2)

这是问题的O(n)解决方案。通过遍历每个节点的树来访问每个节点以及大于该数量的值。由于需要为所有节点访问树,因此复杂度将为O(n)

int sum_all(Node root)
{
    if(root == null) return 0;
    return root.data + sum_all(root.left) + sum_all(root.right);
}

void replace_keys(Node root, int total)
{
    if(root == null) return;

    int leftsum = sum_all(root.left);
    root.data = (total - leftsum - root.data);

    replace_keys(root.left, total);
    replace_keys(root.right, total);
}

void replace_keys(Node root)
{
    int total = sum_all(root);
    replace_keys(root, total);
}

答案 1 :(得分:2)

这个问题可以递归地解决,其背后的想法是:

对于BST中的任何节点:

  • 右子树的所有元素都大于或等于 家长。
  • 左子树的元素值小于父元素。

考虑到这一点,

  • 对于每个节点,我们将其值替换为右边的总和 子树+它自己的价值。 (我们递归计算右子树的总和:))

  • 然后我们转到它的左边孩子并用它替换它的值 父母的价值+它自己的价值+它是正确的子树的最大金额。

当我们遇到没有右子树的节点时,会发生递归的终止条件。当发生这种情况时,节点的值将是它自己的值,然后我们返回。

C / C ++ ish伪代码:

NODE* recSum(root){
    getSum(root);
    return root;
}

int getSum(NODE *n){
    if (n->r == NULL) return n->val;

    else{
        n->val = getSUM(n->r) + n->val;
        n->l->val = getSUM(n) + getSUM((n->l)->r);
    }
}

答案 2 :(得分:0)

首先,遍历BST并将每个节点推送到一个数组中。

其次,对数组进行排序。

最后,再次遍历BST并在阵列的帮助下进行替换。

答案 3 :(得分:0)

ALGO:

按顺序遍历反向,并更新总和

这是java实现

public static void modifyWithSumOfGreaterNodes(BinaryTreeNode<Integer> bst) {
    doModifyWithSumOfGreaterNodes(bst, new MutableInteger(0));      
}

private static void doModifyWithSumOfGreaterNodes(BinaryTreeNode<Integer> bst, MutableInteger sum) {
    if (bst == null) {
        return ;
    }

    doModifyWithSumOfGreaterNodes(bst.getRight(), sum);
    sum.add(bst.getData());
    bst.setData(sum.getValue());
    doModifyWithSumOfGreaterNodes(bst.getLeft(), sum);      
}

这是单元测试

@Test
public void replaceBSTNodesWithSumOfNodesGreaterOrEqualToNodeTest() {

    BinaryTreeNode<Integer> eighty = new BinaryTreeNode<Integer>(80);
    BinaryTreeNode<Integer> sixty = new BinaryTreeNode<Integer>(60);
    BinaryTreeNode<Integer> forty = new BinaryTreeNode<Integer>(40);
    BinaryTreeNode<Integer> twenty = new BinaryTreeNode<Integer>(20);
    BinaryTreeNode<Integer> seventy = new BinaryTreeNode<Integer>(70, sixty, eighty);
    BinaryTreeNode<Integer> thrity = new BinaryTreeNode<Integer>(30, twenty, forty);
    BinaryTreeNode<Integer> root = new BinaryTreeNode<Integer>(50, thrity, seventy);

    BinaryTreeUtil.modifyWithSumOfGreaterNodes(root);

    assertThat(BinaryTreeUtil.iPostOrder(root).toArray(new Integer[0]), equalTo(new Integer[]{350,300,330,210,80,150,260}));


}

答案 4 :(得分:0)

这是java中的完整程序

BinarySearchTree类定义

public class BST<T> {

public Node root;

 static class Node<T>{
 public Node left;  
 public Node right;
 public T data;

 Node(T data){
     this.data =data;
 }
}

}

实际的类定义,其中每个节点都替换为给定BST中所有更大节点的总和

public class TestGreaterNodeBST {



    public static void main(String[] args) {
        BST<Integer> bst = new BST<Integer>();
        bst.root= new BST.Node<Integer>(50);
        bst.root.left =new BST.Node<Integer>(30);
        bst.root.right =new BST.Node<Integer>(80);
        bst.root.right.left =new BST.Node<Integer>(70);
        bst.root.right.left.left =new BST.Node<Integer>(60);
        bst.root.right.right =new BST.Node<Integer>(100);
        bst.root.right.right.right =new BST.Node<Integer>(120);
        bst.root.right.right.right.left =new BST.Node<Integer>(110);
        bst.root.right.right.right.right =new BST.Node<Integer>(150);

        printInOrderDescending(bst.root);
        System.out.println();
        System.out.println();
        transformToGreaterNode(bst.root, 0);
        printInOrderDescending(bst.root);

    }


    static void printInOrderDescending(BST.Node node){

        if(node==null){
            return;
        }

        printInOrderDescending(node.right);
        System.out.println(node.data);
        printInOrderDescending(node.left);

    }



    static Integer transformToGreaterNode(BST.Node<Integer> node, Integer sum){

        if(node==null){
            return sum;
        }


        sum = transformToGreaterNode(node.right, sum);

        Integer data = node.data;
        node.data=sum;
        sum = sum + data;

        sum = transformToGreaterNode(node.left, sum);

        return sum;
    }

}

答案 5 :(得分:0)

您需要具有一个字段名称为sum的对象。进行时,您将更新此总和。我的解决方案是递归的。考虑到我们正在处理排序树(二进制搜索树)这一事实,您需要先遍历正确的子级,然后更新当前节点并求和。然后,遍历左孩子。递归结束时,现有的根将成为大和树的根(每个节点的节点值之和大于或等于同一节点)。

/**
 * Given the root of a binary search tree with distinct values, modify it so that every node has a new value equal to the sum of the values of the original tree that are greater than or equal to node.val.
 * <p>
 * As a reminder, a binary search tree is a tree that satisfies these constraints:
 * <p>
 * The left subtree of a node contains only nodes with keys less than the node's key.
 * The right subtree of a node contains only nodes with keys greater than the node's key.
 * Both the left and right subtrees must also be binary search trees.
 * Reference: LeetCode
 */
public class BinarySearchTreeToGreaterSumTree {

    class Sum {
        public int sum = 0;
    }

    public static void main(String[] args) {
/*
public class TreeNode {

    Integer val;
    TreeNode left;
    TreeNode right;

    TreeNode(Integer x) {
        val = x;
    }

    TreeNode(TreeNode treeNode) {
        if (treeNode != null) {
            this.val = treeNode.val;
            this.left = new TreeNode(treeNode.left);
            this.right = new TreeNode(treeNode.right);
        }
    }

}
 */
        TreeNode node0 = new TreeNode(0);
        TreeNode node1 = new TreeNode(1);
        TreeNode node2 = new TreeNode(2);
        TreeNode node3 = new TreeNode(3);
        TreeNode node4 = new TreeNode(4);
        TreeNode node5 = new TreeNode(5);
        TreeNode node6 = new TreeNode(6);
        TreeNode node7 = new TreeNode(7);
        TreeNode node8 = new TreeNode(8);
        node4.left = node1;
        node4.right = node6;
        node1.left = node0;
        node1.right = node2;
        node2.right = node3;
        node6.left = node5;
        node6.right = node7;
        node7.right = node8;

        BinarySearchTreeToGreaterSumTree bstToGST = new BinarySearchTreeToGreaterSumTree();
        // the input of this method should be the root of the tree
        TreeNode result = bstToGST.bstToGst(node4);
        System.out.println();
    }

    /**
     * Builds a GST.
     *
     * @param root The root of the binary search tree
     * @return The GST
     */
    public TreeNode bstToGst(TreeNode root) {
        if (root != null) {
            Sum sum = new Sum();
            buildGST(root, sum);
        }
        return root;
    }

    /**
     * A recursive method to build the Greater Sum Tree.
     *
     * @param currentNode The current node
     * @param sum         The current summation
     */
    private void buildGST(TreeNode currentNode, Sum sum) {
        if (currentNode == null)
            return;
        // Call build GST on the right child
        TreeNode r = currentNode.right;
        buildGST(r, sum);
        // Update the current sum with the value of the current node
        sum.sum = sum.sum + currentNode.val;
        // Update the value of the current node with the new sum
        currentNode.val = sum.sum;
        // Call build GST on the left child with the updated sum
        TreeNode l = currentNode.left;
        buildGST(l, sum);
    }

}

我希望这会有所帮助。