get (tree node val - (subtree val sum))

本文介绍了一种算法,该算法通过递归及非递归方式计算给定树中每个节点的值与其左右子树之和的差值。递归实现简洁直观,而非递归方法使用栈和哈希映射进行高效计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给一个tree,返回每个点左右子树的和与自己值的差,用递归做,还问了不递归怎么做

package tree;

import java.util.*;

import z_dataStructure.TreeNode;

public class TreeNodeMinusSubtreeSum {

	public static void main(String[] args) {
		TreeNode root = new TreeNode(1);
		TreeNode node2 = new TreeNode(2);
		TreeNode node3 = new TreeNode(3);
		TreeNode node4 = new TreeNode(4);
		TreeNode node5 = new TreeNode(5);
		root.left = node2;
		root.right = node3;
		node3.left = node4;
		node3.right = node5;

		for (int subsum : treeNodeWithSubtreeSum(root)) {
			System.out.println(subsum);
		}
		ArrayList<Integer> res = new ArrayList<Integer>();
		treeNodeWithSubtreeSum1(root, res);
		for (int subsum : res) {
			System.out.println(subsum);
		}
	}
	
	public static int treeNodeWithSubtreeSum1(TreeNode root, ArrayList<Integer> res){
		if (root == null) {
			return 0;
		}
		int leftSubtree = treeNodeWithSubtreeSum1(root.left, res);
		int rightSubtree = treeNodeWithSubtreeSum1(root.right, res);
		int sum = root.val - leftSubtree - rightSubtree;
		res.add(sum);
		return root.val + leftSubtree + rightSubtree;
	}
	
	 public static ArrayList<Integer> treeNodeWithSubtreeSum(TreeNode root) {
         ArrayList<Integer> ret = new ArrayList<Integer>();
         if (root == null)
                 return ret;
         Stack<TreeNode> s = new Stack<TreeNode>();
         HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
         s.add(root);
         TreeNode pre = null;
         while (!s.isEmpty()) {
                 TreeNode cur = s.peek();
                 if (pre == null || pre.left == cur || pre.right == cur) {
                         if (cur.left != null) {
                                 s.push(cur.left);
                         } else if (cur.right != null) {
                                 s.push(cur.right);
                         } else {
                                 s.pop();
                                 map.put(cur.val, 0);
                                 ret.add(cur.val - map.get(cur.val));
                         }
                 } else if (cur.left == pre) {
                         if (cur.right != null) {
                                 map.put(cur.val, map.get(pre.val) + pre.val);
                                 s.push(cur.right);
                         } else {
                                 s.pop();
                                 map.put(cur.val, map.get(pre.val) + pre.val);
                                 ret.add(cur.val - map.get(cur.val));
                         }
                 } else if (cur.right == pre) {
                         s.pop();
                         int tmp = 0;
                         if (map.containsKey(cur.val))
                                 tmp = map.get(cur.val);
                         tmp += map.get(pre.val) + pre.val;
                         map.put(cur.val, tmp);
                         ret.add(cur.val - map.get(cur.val));
                 }
                 pre = cur;
         }
         return ret;
 }
}


这是一个有趣的二叉树性质题目。我们构建一种特殊的二叉树,其每个节点的值等于它的左子树的所有节点值之和加上右子树的所有节点值之和。下面逐步分析这种特殊二叉树的特点及其构造过程。 --- ### 定义这样的二叉树 #### 节点结构 首先定义一个基本的二叉树节点结构如下: ```c++ struct TreeNode { int val; // 存储当前节点的数值 TreeNode* left; // 左孩子指针 TreeNode* right; // 右孩子指针 TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; ``` #### 特殊规则描述 对于每一个非叶子节点`node`来说, - 其自身的值 `val(node)` 应该等同于 **所有在其左子树内各节点的值总合 加上 所有在其右子树内的各节点值总合**。 也就是说, \[ val(\text{node}) = \sum_{left-subtree} + \sum_{right-subtree} \] 其中若无对应的左右子树,则默认它们各自的求和结果为零。 --- ### 构建及验证算法 我们可以递归地实现这一特性校验或者生成符合此特性的新树。下面是伪代码思路: 1. 对任意给定的一个根结点开始遍历整个二叉树; 2. 计算当前节点下左右两部分各自元素之累加,并更新当前节点存储的值为此计算所得的结果; 3. 再分别处理这两侧分支直到触及到底层叶子为止(因为叶节点天然满足条件因为他们没有任何子孙贡献额外数值). 完整代码片段展示(C++版): ```cpp // Helper function to calculate subtree sum and modify values accordingly. int adjustTree(TreeNode* node){ if(!node)return 0; int lSum=adjustTree(node->left); // Recursively get Left Sub Tree Sum int rSum=adjustTree(node->right); // Similarly Right One too... int total=lSum+rSum; // Current Node Value As Per Rule Defined Above ! node->val=total; return node->val+node->val; // Return Total Including This Node Itself For Parent To Use.. } void makeSpecialBinaryTree(TreeNode *root){ adjustTree(root); // Call helper from root of the tree ... } ``` 上述函数将调整输入的一棵普通的二叉搜索树成为一个按照特定规则改变后的版本即"Left Children Plus Right Equals Self"形式的新树木. --- ### 注意事项 由于每一次都要从底部往上逐级重新核算数值,所以时间复杂度大概率会达到O(n),n代表总的节点数目的大小。此外,这个转换过程中并未破坏原有链接关系只是单纯更改了内部携带的数据而已。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值