如果递归需要返回结果,最后一步是合并子问题的结果 写一个案例(本质上用到了后序遍历)

当使用递归算法需要返回结果,并且最后一步是合并子问题的结果时,一个典型的案例是二叉树的遍历算法,比如二叉树的前序遍历。在前序遍历中,我们按照“根节点-左子树-右子树”的顺序访问节点,并且递归地处理左子树和右子树,最后将子树遍历的结果合并到总的结果中。不过,对于前序遍历来说,由于我们直接打印或者处理根节点,然后再递归遍历左右子树,实际上并没有显式地“合并”子问题的结果到一个单一的数据结构中,因为遍历的过程本身就是逐步处理并“合并”的。不过,为了展示这个概念,我们可以考虑一个稍微变通的例子:计算二叉树中所有节点的值之和。

以下是一个使用Python实现的计算二叉树节点值之和的递归案例,这里我们将“合并”子问题的结果(即左右子树节点值的和)来得到整棵树节点值的和:

python
class TreeNode:
def init(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right

def sumOfTreeNodes(root):
# 基本情况:如果树为空,则返回0
if root is None:
return 0
# 递归地计算左子树节点值的和
left_sum = sumOfTreeNodes(root.left)
# 递归地计算右子树节点值的和
right_sum = sumOfTreeNodes(root.right)
# 合并子问题的结果:当前节点的值与左右子树节点值的和相加
return root.val + left_sum + right_sum

示例用法

构建一棵简单的二叉树

1

/ \

2 3

/ \

4 5

root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.right.left = TreeNode(4)
root.right.right = TreeNode(5)

计算二叉树中所有节点的值之和

print(sumOfTreeNodes(root)) # 输出: 15
在这个例子中,sumOfTreeNodes 函数通过递归地计算左子树和右子树节点值的和,并将这些和与当前节点的值相加,从而实现了“合并子问题的结果”的目标。这是递归算法中非常常见的一种模式,即“分而治之”的策略。

在Java中,实现上述计算二叉树节点值之和的代码与我之前给出的Python示例非常相似。下面是一个Java版本的实现:

首先,定义TreeNode类来表示二叉树的节点:

java
class TreeNode {
int val;
TreeNode left;
TreeNode right;

TreeNode(int val) {  
    this.val = val;  
}  

}
然后,实现一个方法来计算二叉树中所有节点的值之和:

java
public class BinaryTreeSum {

// 递归方法计算二叉树中所有节点的值之和  
public static int sumOfTreeNodes(TreeNode root) {  
    // 基本情况:如果树为空,则返回0  
    if (root == null) {  
        return 0;  
    }  
    // 递归地计算左子树节点值的和  
    int leftSum = sumOfTreeNodes(root.left);  
    // 递归地计算右子树节点值的和  
    int rightSum = sumOfTreeNodes(root.right);  
    // 合并子问题的结果:当前节点的值与左右子树节点值的和相加  
    return root.val + leftSum + rightSum;  
}  

public static void main(String[] args) {  
    // 构建一棵简单的二叉树  
    //       1  
    //      / \  
    //     2   3  
    //        / \  
    //       4   5  
    TreeNode root = new TreeNode(1);  
    root.left = new TreeNode(2);  
    root.right = new TreeNode(3);  
    root.right.left = new TreeNode(4);  
    root.right.right = new TreeNode(5);  

    // 计算二叉树中所有节点的值之和  
    int sum = sumOfTreeNodes(root);  
    System.out.println("Sum of tree nodes: " + sum); // 输出: Sum of tree nodes: 15  
}  

}
在这个Java实现中,TreeNode类用于表示二叉树的节点,它包含了一个整数值val和两个指向其子节点的引用left和right。sumOfTreeNodes方法是一个递归方法,它首先检查当前节点是否为空(即基本情况),然后递归地计算左子树和右子树中所有节点的值之和,并将这些和与当前节点的值相加得到最终结果。main方法用于构建一棵示例二叉树并调用sumOfTreeNodes方法来计算并打印出所有节点的值之和。

public static int sumOfTreeNodes(TreeNode root) {
// 基本情况:如果树为空,则返回0
if (root == null) {
return 0;
}
// 递归地计算左子树节点值的和
int leftSum = sumOfTreeNodes(root.left);
// 递归地计算右子树节点值的和
int rightSum = sumOfTreeNodes(root.right);
// 合并子问题的结果:当前节点的值与左右子树节点值的和相加
return root.val + leftSum + rightSum;
} return root.val + leftSum + rightSum; 值的变化过程

在递归函数 sumOfTreeNodes 中,return root.val + leftSum + rightSum; 这行代码的值变化过程是一个典型的递归过程,它展示了如何从二叉树的底部(叶子节点)开始,逐步向上合并子树的结果,直到达到根节点。

为了更清晰地理解这个过程,我们可以考虑一个具体的二叉树,比如你之前给出的例子:

1
/ \
2 3
/ \
4 5
当我们调用 sumOfTreeNodes(root) 时(其中 root 是值为 1 的节点),函数会按照以下步骤执行:

检查基本情况:root 不为空,所以继续执行。
递归左子树:调用 sumOfTreeNodes(root.left),即 sumOfTreeNodes(2)。
2 的左子树为空,所以 sumOfTreeNodes(null) 返回 0。
2 的右子树也为空,所以 sumOfTreeNodes(null) 返回 0。
因此,sumOfTreeNodes(2) 返回 2 + 0 + 0 = 2。
递归右子树:调用 sumOfTreeNodes(root.right),即 sumOfTreeNodes(3)。
接下来,对于 3 的左子树 4,sumOfTreeNodes(4) 会返回 4(因为 4 没有子节点)。
对于 3 的右子树 5,sumOfTreeNodes(5) 会返回 5(因为 5 也没有子节点)。
因此,sumOfTreeNodes(3) 返回 3 + 4 + 5 = 12。
合并结果:现在我们已经有了左子树的和 leftSum = 2 和右子树的和 rightSum = 12,我们可以计算整棵树的和:
return root.val + leftSum + rightSum; 变为 return 1 + 2 + 12;
因此,最终返回 15。
值的变化过程可以看作是从叶子节点(深度最大的节点)开始,逐步向上合并子树的和,直到达到根节点。在这个过程中,每个节点的值都会与其子树的和相加,从而得到以该节点为根的子树的所有节点值的总和。最终,当这个过程到达根节点时,我们就得到了整棵树的所有节点值的总和。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值