牛客13593 大家一起来数二叉树吧 简单dp

题目连接:大家一起来数二叉树吧

题目描述

某一天,Zzq正在上数据结构课。老师在讲台上面讲着二叉树,zzq在下面发着呆。
突然zzq想到一个问题:对于一个n个节点,m个叶子的二叉树,有多少种形态呐?你能告诉他吗?
对于第一组样例的解释
在这里插入图片描述

输入描述

每一组输入一行,两个正整数n,m(n<=50)意义如题目

输出描述

每一行输出一个数,表示相应询问的答案取模1000000007

题意

n个节点,m个叶子,问有多少种形态的二叉树

题解

二叉树的每一次延伸一个节点相当于加上一棵子树,考虑到是二叉树,所以考虑一左一右相当于*2。所以当你需要x个节点,其中有y个叶子时候,就需要考虑x个节点y个叶子拆分后分配到左右子树上,而且拆分后又变成了一个子子树,这个子子树又有它本身多种形态,所以需要乘法。
故dp核心式子是 dp[i][j]=(dp[i][j]+dp[x][y]dp[i-x-1][j-y]%mod)%mod,
中i代表的总节点数,j代表的是总叶子数,x代表的是左子树的节点数,y代表的是左子树的叶子数,而i-x-1代表的右子树的节点数(-1是取出头节点),y-代表的是左子树的叶子数。

#pragma GCC optimize(2)
#include<bits/stdc++.h> 
using namespace std;
#define ll long long
#define endl "\n"
const int mod=1e9+7;
ll dp[55][55];
int main(){
    ios_base::sync_with_stdio(0);cin.tie(0);
    dp[0][0]=1;dp[1][1]=1;
   	for(int i=1;i<=50;i++)
   		for(int j=1;j<=i;j++)
			for(int x=0;x<i;x++)
				for(int y=0;y<=j;y++)
					dp[i][j]=(dp[i][j]+dp[x][y]*dp[i-x-1][j-y]%mod)%mod;		
	int n,m;
	while(cin>>n>>m)cout<<dp[n][m]<<endl;
    return 0;
} 
题目要求:给定一个二叉树和一个整target,找出所有从根节点到叶子节点路径之和等于target的路径。 解题思路:可以使用深度优先搜索(DFS)的方法来解决该问题。首先定义一个辅助函来进行递归搜索,该辅助函的参包括当前节点、当前路径、当前路径的和以及目标和。在搜索过程中,需要维护一个组来保存当前节点到根节点的路径。搜索过程如下: 1. 如果当前节点为空,则返回。 2. 将当前节点的值添加到当前路径中。 3. 将当前节点的值累加到当前路径的和中。 4. 如果当前节点是叶子节点,且当前路径的和等于目标和,则将当前路径添加到结果中。 5. 递归地搜索当前节点的左子树和右子树,并传递更新后的当前路径和当前路径的和。 最后,在主函中调用辅助函,并返回结果即可。 以下是题目的完整代码实现: ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def pathSum(root, target): def dfs(node, path, path_sum, target, res): if not node: return path.append(node.val) path_sum += node.val if not node.left and not node.right: # 当前节点是叶子节点 if path_sum == target: res.append(path[:]) # 注意需要复制一份path,否则会出现问题 dfs(node.left, path, path_sum, target, res) dfs(node.right, path, path_sum, target, res) path.pop() # 回溯到父节点,去掉当前节点 path_sum -= node.val res = [] dfs(root, [], 0, target, res) return res ``` 这样就能找出所有满足路径和等于目标和的路径了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值