《算法分析与设计》Week 8

本文介绍了一种使用动态规划解决独特二叉搜索树计数问题的方法。通过定义状态转移方程,递推地计算出给定节点数n时所有可能的独特二叉搜索树的数量。

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

96. Unique Binary Search Trees


Description:

Given n, how many structurally unique BST's (binary search trees) that store values 1...n?

For example,
Given n = 3, there are a total of 5 unique BST's.

   1         3     3      2      1
    \       /     /      / \      \
     3     2     1      1   3      2
    /     /       \                 \
   2     1         2                 3

Solution:

一、题意理解

     给定一个数n,有多少个异构的二叉搜索树用来存储1...n?所谓异构,类似化学中的同素异构体,就是组成元素相同,但是在空间结构上的组成方式不同。


二、分析

     1、可以用动态规划来解,找到状态转移方程。要寻找节点数为n的二叉搜索树的异构体数量,可以依次寻找限制以i(i=1,2,...,n)为根节点的二叉搜索树的异构体,然后将其累加即可。不妨设:

          G(n):存储序列1...n的二叉搜索树的异构体数目,也是我们要求解的目标。

          F(i, n):存储序列1...n时,限制以i为根节点的二叉搜索树的异构体数目。

     2、而动态规划,无非就是用已经求解的值来得到另一个条件下的值。有了以上的假设,很容易得到如下的式子:

          G(n) = F(1, n) + F(2, n) + F(3, n) + ... + F(n, n)

          F(i, n) = G(i - 1) * G(n - i)

          第一个式子很好理解,就是一个累加。对于第二个式子来说,比如n = 6,当限制以3为根节点时,{1,2}组成根节点3的左子树,{4,5,6}组成根节点3的右子树,而左子树{1,2}的异构体数目自然等于G(3-1) = G(2),右子树{4,5,6}的异构体数目和{1,2,3}的异构体数目相同,为G(6-3) = G(3)。所以F(3, 6) = G(2) * G(3)。

     3、结合上述两个式子,就可以得到最终的状态转移方程:

          G(n) = G(0) * G(n-1) + G(1) * G(n-2) + G(2) * G(n-3) + ... + G(n-1) * G(0)

     4、代码如下:   

class Solution {
public:
    int numTrees(int n) {
        int *G = new int[n+2];
        G[0] = G[1] = 1;
        for(int i=2; i<=n; ++i)
        {
            G[i] = 0;
            for(int j=1; j<=i; ++j)
            {
                G[i] += G[j-1] * G[i-j];
            }
        }
        int tmp = G[n];
        delete G;
        return tmp;
    }
};




### 关于山东大学程序设计 Week5 的课程资料作业 尽管当前提供的引用并未直接提及山东大学程序设计思维实践的第5周具体内容,但从已有参考资料来看,可以推测该课程可能涉及的内容范围以及学习目标。 通常情况下,在类似的程序设计课程中,第五周的学习重点可能围绕以下几个方面展开: #### 可能的主题方向 1. **动态规划基础** 动态规划是一种解决多阶段决策过程最优化问题的方法。它通过将复杂问题分解成更简单的子问题来求解最优解[^2]。如果 Week5 涉及此主题,学生可能会接触到经典的动态规划问题,例如背包问题、最长公共子序列(LCS)、矩阵链乘法等。 2. **贪心算法的应用** 贪心算法的核心在于每一步都做出局部最优的选择,期望最终达到全局最优解。这种策略适用于某些特定场景下的问题,比如活动选择问题、霍夫曼编码等问题[^1]。 3. **图论初步** 图论作为离散数学的重要分支之一,在计算机科学中有广泛的应用价值。Week5 也可能引入基本概念如连通性检测、最小生成树(Kruskal 和 Prim 算法),或者单源最短路径(Dijkstra 算法)[^4]。 4. **高级数据结构介绍** 高级的数据结构能够显著提升解决问题效率。例如堆(Heap)用于实现优先队列;并查集(Union-Find Set)用来处理集合合并操作等等[^3]。 以下是基于上述假设整理的一道典型练习题及其解答思路: --- #### 练习题示例:最大连续子数组和 给定一个整数数组 `nums` ,找到其中具有最大和的一个连续子数组,并返回其总和。 ##### 思路分析: 采用 Kadane's Algorithm 来高效完成任务。核心思想是在遍历过程中维护两个变量——当前的最大子数组结束位置处的累加值(`current_sum`)以及迄今为止发现的整体最大值(`max_so_far`)。每当遇到新的元素时更新这两个量即可得出答案。 ```python def maxSubArray(nums): current_sum = nums[0] max_so_far = nums[0] for i in range(1, len(nums)): # 判断是否应该重新开始一个新的子数组还是延续之前的 current_sum = max(nums[i], current_sum + nums[i]) # 更新整体最大值 max_so_far = max(max_so_far, current_sum) return max_so_far ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值