程序员代码面试指南刷题--第三章.统计和生成所有不同的二叉树

题目描述
给出一个整数 n,如果 n < 1,代表空树,否则代表中序遍历的结果为 {1, 2, 3… n}。请输出可能的二叉树结构有多少。
输入描述:

第一行输入一个整数 n。

输出描述:

输出一个整数对 1e9 + 7 取模的值表示答案。

示例1

输入

7

输出

429

解法一:动态规划

import java.io.*;
import java.util.*;
public class Main{
    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int num = Integer.parseInt(br.readLine());
        int res = getSum(num);
        System.out.println(res);
    }
    public static int getSum(int num){
        if(num<2) return 1;
        long[] nums = new long[num+1];
        nums[0] = 1;
        //动态规划
        for(int i=1;i<num+1;i++){
            for(int j=1;j<i+1;j++){
                nums[i] += nums[j-1]*nums[i-j];
                nums[i] %= 1000000007;
            }
        }
        return (int)nums[num]%1000000007;
    }
}

解法二:卡特兰数

import java.io.InputStreamReader;
import java.io.IOException;
import java.io.BufferedReader;
 
public class Main {
      
    private static final int modNum = (int)1e9 + 7;
      
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.valueOf(in.readLine());
        System.out.println(getNumOfTree(n));
    }
      
    // 卡特兰数 h(1)=1, h(n) = (4 * n - 2) / (n + 1) * h(n - 1)
    // 线性求逆元 inv[i]=-(mod/i)*inv[i%mod]
    public static long getNumOfTree(int n) {
        long res = 1;
        long[] inv = new long[n + 3];
        inv[1] = 1;
        for(int i = 2; i < n + 3; i++) {
            inv[i] = (modNum - modNum / i) * inv[modNum % i] % modNum;
        }
        for (int i = 0; i < n; i++) {
            res = res * ((4 * i + 2) * inv[i + 2] % modNum) % modNum;
        }
        return res;
    }
}

进阶问题:输出所有的树

public List<TreeNode> generate(int n){
 	return generate(1,n);
}
public List<TreeNode> generate(int start,int end){
	List<TreeNode> res = new ArrayList<>();
	if(start>end){
		res.add(null);
		return res;
	}
	TreeNode head = null;
	for(int i=start;i<=end;i++){
		head = new TreeNode(i);
		List<TreeNode> left = generate(start,i-1);
		List<TreeNode> right = generate(i+1,end);
		for(TreeNode l:left){
			for(TreeNode r:right){
				head.left = l;
				head.right = r;
				res.add(cloneTree(head));
			}
		}
	}
	return res;
}
public TreeNode cloneTree(TreeNode head){
	if(head==null){
		return null;
	}
	TreeNode newHead = new TreeNode(head.val);
	newHead.left = cloneTree(head.left);
	newHead.right = cloneTree(head.right);
	return newHead;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值