1.1 一维数组

       数组是最简单的,也最基础的数据结构。数组是一个有序的数据集合,用索引(或者叫下标)访问数据。在大多数编程语言,比如C/C++/java/javascript中,数组的索引都是以0开始。它的逻辑结构是一段连续的空间(因为虚拟内存的原因,实际情况下大数组可能由多个不连续的内存页组成)。

       如下图所示:

1

1

2

3

5

8

0

1

2

3

4

5

       上图中,第一行表示数据第二行表示索引

       一维数组,我会以一个案例来开始。

       假设有这么一个需求,求11个点能构成多少种二叉树。比如3个点,可以构成五种二叉树:

       按照序言里的步骤,我们第一步是仔细研究需求。从上图看,所有的树都是线性结构。那么不同在哪里?可见这个问题其实是数学里的组合计数问题。

       解题思路

       以3个点为例子,作为二叉树必须要有根节点。那么利用分类归纳法,可以这样计算出来。

       场景1 只有左节点

 

       场景2 左右节点都存在

       场景3 只有右节点

 

       以上场景实际上是什么问题?

       是结点的左右分配问题!那么假设N个结点能组成二叉树的数目为C(n)

       场景1

       左节点数量2,右节点数量0,树的数量为左边树的数量C(2)*右边树的数量 C(0)

       场景2

       左节点数量1,右节点数量1,树的数量为左边树的数量C(1)*右边树的数量 C(1)

       场景3

       左节点数量0,右节点数量2,树的数量为左边树的数量C(0)*右边树的数量 C(2)

       所以对于N个结点,就可以分成N种场景。左边的数目确定了,右边的数目就也确定了。所以可以写出递归公式,是乘积的求和:

       

       那么这个问题,用什么数据结构呢?根据递归公式,可以清楚地知道我们需要存储C(0)到C(n-1)的所有数据,所以这个问题,一维数组这种数据结构最合适了。经过分析之后,代码就非常容易写了。

       Python代码

def c(n):
    if n < 2:
        return 1
    array = [0] * (n + 1)
    array[1] = array[0] = 1
    for i in range(2, n + 1):
        for j in range(0, i):
            array[i] += array[j] * array[i - j - 1]
    return array[n]

       需要注意的是python中没有严格意义上的数组。为了严谨,这里附上java代码:

    public static int catalan(int n) {
        if (n < 2) {
            return 1;
        }
        int[] array = new int[n + 1];
        array[1] = array[0] = 1;
        for (int i = 2; i < n + 1; i++) {
            for (int j = 0; j < i; j++) {
                array[i] += array[j] * array[i - j - 1];
            }
        }
        return array[n];
    }

       这个数列就是著名的明安图数列,也叫卡特兰数列。不过在我们这个例子中,与卡特兰数列错了一位而已。

       我们的例子中c(0)=1 c(1)=1 c(2)=2……

       而卡特兰数列是c(1)=1 c(2)=1 c(3)=2……

       递归公式,与卡特兰数列一模一样。

       这个题目属于数学专业研究生的组合计数学课程。其实我是反对把知识分什么中学知识、大学知识、硕士阶段、博士阶段的。我们要做的仅仅是,按照编程的套路,先仔细分析需求,选择合适的数据结构,然后设计算法,编写代码,就可以了。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

醒过来摸鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值