我想知道以下问题的算法:
“给定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
请帮忙。 感谢
答案 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);
}
}
我希望这会有所帮助。