华为od(D卷)二叉树计算

题目描述

给出一个二叉树如下图所示:

     6
    / \
   7   9
    \  /  
    -2 6  

请由该二叉树生成一个新的二叉树,它满足其树中的每个节点将包含原始树中的左子树和右子树的和。

      20 (7-2+9+6)
     /   \
    -2    6
     \   /  
     0  0 

左子树表示该节点左侧叶子节点为根节点的一颗新树;右子树表示该节点右侧叶子节点为根节点的一颗新树

输入描述

2行整数,
第1行表示二叉树的中序遍历,
第2行表示二叉树的前序遍历,以空格分割

例如:

7 -2 6 6 9
6 7 -2 9 6

输出描述

1行整数,表示求和树的中序遍历,以空格分割

例如:

输出1 -2 0 20 0 6

示例1

输入:
-3 12 6 8 9 -10 -7
8 12 -3 6 -10 9 -7

输出:
0 3 0 7 0 2 0

思路

1 . 前序中序构造二叉树

前序: 中左右; 判断“中”是第一个元素。
中序: 根据前序找到的“中” ,判断左右子树是谁。(此时可以提前计算左右子树的和)

代码

public class Demo11 {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        // 中序
        int[] in = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        // 前序
        int[] pre = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        // 最终中序结果
        int[] resMid = new int[in.length];
        buildTree(pre, in, resMid, 0, pre.length, 0, in.length);
        System.out.println(Arrays.toString(resMid));
        scanner.close();

    }

    /**
     * @param pre      前序数组
     * @param in       中序数组
     * @param resMid   最终输出中序结果
     * @param preStart 前序开始索引
     * @param preEnd   前序结束索引
     * @param inStart  中序开始索引
     * @param inEnd    中序结束索引
     */
    public static void buildTree(int[] pre, int[] in, int[] resMid, int preStart, int preEnd, int inStart, int inEnd) {

        if (preStart == preEnd || inStart == inEnd) {
            return;
        }
        if (preEnd - preStart == 1 && inEnd - inStart == 1) {
            return;
        }
        
        // 中  为第一个元素
        int rootValue = pre[preStart];

        // 中  在中序中的位置
        int index = 0;
        for (int i = inStart; i < inEnd; i++) {
            if (in[i] == rootValue) {
                index = i;
                break;
            }
        }
        
        // 中序数组 左子树
        int inLeftStart = inStart;
        int inLeftEnd = index;
        // 中序数组的右子树
        int inRightStart = index + 1;
        int inRightEnd = inEnd;

        // 前序数组的  左子树
        int preLeftStart = preStart + 1;
        int preLeftEnd = preLeftStart + (index - inStart);
        // 前序数组的 右子树
        int preRightStart = preLeftEnd;
        int preRightEnd = preEnd;

        // 计算左右子树的和
        int[] inLeft = Arrays.copyOfRange(in, inLeftStart, inLeftEnd);
        int[] inRight = Arrays.copyOfRange(in, inRightStart, inRightEnd);
        resMid[index] = Arrays.stream(inLeft).sum() +
                Arrays.stream(inRight).sum();

        // 递归
        buildTree(pre, in, resMid, preLeftStart, preLeftEnd, inLeftStart, inLeftEnd);
        buildTree(pre, in, resMid, preRightStart, preRightEnd, inRightStart, inRightEnd);
    }
}

### 华为OD项目中二叉树计算算法实现 #### 层次遍历的实现 对于给定的输入,可以通过构建一棵二叉树并对其进行层次遍历来得到所需的输出。以下是基于引用[1]中的例子实现的一个解决方案: ```cpp #include <iostream> #include <queue> #include <unordered_map> using namespace std; struct TreeNode { char val; TreeNode* left; TreeNode* right; TreeNode(char v) : val(v), left(nullptr), right(nullptr) {} }; TreeNode* buildTree(const string& preorder, const string& inorder) { unordered_map<char, int> indexMap; for (int i = 0; i < inorder.size(); ++i) { indexMap[inorder[i]] = i; } auto helper = [&](auto&& self, const string& pre, int pStart, int pEnd, const string& ino, int iStart, int iEnd) -> TreeNode* { if (pStart >= pEnd || iStart >= iEnd) return nullptr; TreeNode* root = new TreeNode(pre[pStart]); int idx = indexMap[root->val]; int leftSize = idx - iStart; root->left = self(self, pre, pStart + 1, pStart + 1 + leftSize, ino, iStart, idx); root->right = self(self, pre, pStart + 1 + leftSize, pEnd, ino, idx + 1, iEnd); return root; }; return helper(helper, preorder, 0, preorder.length(), inorder, 0, inorder.length()); } string levelOrder(TreeNode* root) { queue<TreeNode*> q; string result = ""; if (!root) return result; q.push(root); while (!q.empty()) { TreeNode* node = q.front(); q.pop(); result += node->val; if (node->left) q.push(node->left); if (node->right) q.push(node->right); } return result; } void solve() { string preorder, inorder; cin >> preorder >> inorder; TreeNode* tree = buildTree(preorder, inorder); cout << levelOrder(tree) << endl; } ``` 上述代码实现了通过前序和中序序列重建二叉树,并进行了层次遍历[^1]。 --- #### 新二叉树生成逻辑 根据引用[2][^2] 和 引用[3][^3] 的描述,可以设计一种新的二叉树结构,其中每个节点存储的是其左右子树之和。这种转换的核心在于递归地更新每一个节点的值为其左右子树的总和。 下面是具体的实现方法: ```cpp // 定义结点结构体 struct SumNode { int sumValue; SumNode *left, *right; SumNode(int s) : sumValue(s), left(NULL), right(NULL) {} }; SumNode* convertToSumTree(TreeNode* originalRoot) { if (!originalRoot) return NULL; // 创建对应的新节点 SumNode* newNode = new SumNode(0); // 如果当前节点无孩子,则返回零值节点 if (!originalRoot->left && !originalRoot->right){ delete newNode; return NULL; } // 对于有孩子的节点,递归处理左右子树 newNode->left = convertToSumTree(originalRoot->left); newNode->right = convertToSumTree(originalRoot->right); // 更新当前节点的sumValue为左右子树的和 int leftVal = (newNode->left ? newNode->left->sumValue : 0); int rightVal = (newNode->right ? newNode->right->sumValue : 0); newNode->sumValue = leftVal + rightVal; return newNode; } ``` 此函数 `convertToSumTree` 将原始二叉树转化为一个新的二叉树,在这个过程中会忽略掉那些没有子节点的叶节点[^2]^. --- #### 综合应用实例 假设我们有一个简单的二叉树作为输入数据,我们可以综合以上两个部分来完成整个流程: ```cpp int main(){ string preorder="CBEFDA",inorder="CBAEDF"; TreeNode* originalTree=buildTree(preorder,inorder); SumNode* sumTree=convertToSumTree(originalTree); // 进一步操作sumTree... return 0; } ``` 这里展示了如何先建立原生二叉树再将其转成求和形式的新二叉树[^4]. ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值