平衡二叉树--c#求解--英雄会在线编程题目

来源:互联网 发布:淘宝直播运营公司 编辑:程序博客网 时间:2024/04/29 03:42

      这几天写了写了几道题,觉得这道平衡二叉树的题有点意思,就把他的c#算法写出来,不足之处请大家指点。

先看题目:

平衡二叉树

  • 难 度 等 级:

    题目详情

    平衡二叉树的定义是递归定义的:

    (1) 单个节点是平衡二叉树

    (2)平衡二叉树的左右子树分别都是平衡二叉树

    (3)平衡二叉树的左右子树高度差不超过1。

    求n个节点有m个叶子节点的平衡二叉树个数 (0<m <= n<=20)。


    例如:

    n = 1,m = 1,输出:1;

    n = 2,m = 1,输出:2;

    n = 2,m = 2,输出:0。

     

     

    分析:

    1、看完这题,从n=2,m=1,有两种结果,说明,这道题要考虑左右树交换位置,即假设找到一个满足条件的平衡二叉树,左右子树交换位置,也可能得到一个答案。

    2、二叉树的一般原理可以得到,n=左右子树的节点和+1

    3、同理可以得到:m=左右子树的叶子数和

    4、每一个层级的最少节点数=左右子树最少节点数之和(n>1)

    这一点什么意思呢?

    举例来说吧,一个节点,层级是1,,也只能是1,。

    对于2个层级的平衡树,如果要满足条件,最少需要2个节点,1个叶子,最多3个节点,2个叶子

    对于3个层级的平衡树,如果要满足条件:

          最少节点=2级的最少节点数+1级的最少节点数+1

         最少叶子=2级的最少叶子数+1级的最少叶子数

         最多节点=2级的最多节点数*2+1

         最多叶子=2级的最多叶子数*2

     

    有了这个推理过程,我们很容易得到x级的平衡树的最少节点数、叶子数,最多节点数、叶子数

    为什么要得到这个推论和结果呢?因为给我们的是节点数和叶子数,所以我们要知道这样的条件能够生成多少级别的平衡二叉树

     

    思路:

    通过上面的分析,我们就可以将问题转换为,对于n,m可以在层级为x的平衡二叉树上有多少种方案,

    当x>2时,可以将x降级为左右树的可能出现情况,这样就能得到结果=left*right

     

    1、首先构造这个最大、最小节点叶子数的字典,当然,临时求出来也行,反正规律已经分析出来的:

    static Dictionary<int, List<int>> dic;

    dic = new Dictionary<int, List<int>>();

    for (int i = 1; i <= 6; i++)
                {
                    List<int> list = new List<int>();
                    if (i == 1)
                    {
                        list.Add(1);
                        list.Add(1);
                        list.Add(1);
                        list.Add(1);
                    }
                    if (i == 2)
                    {
                        list.Add(2);
                        list.Add(1);
                        list.Add(3);
                        list.Add(2);
                    }
                    if (i > 2)
                    {
                        list.Add(dic[i - 1][0] + dic[i - 2][0]+1);
                        list.Add(dic[i - 1][1] + dic[i - 2][1] );
                        list.Add(dic[i - 1][2]*2 +1);
                        list.Add(dic[i - 1][3] * 2 );
                    }
                    dic.Add(i, list);
                }

    这里自己定义list[0]表示最少节点数,依次向后表示最少叶子数,最大节点数,最大叶子数

     

    2、构造了范围集字典,下一步创建结果集字典

    因为3级的结果={左1级*右边2级+左边2级*右边1级+左边2级*右边2级)的结果和

    所以,我们先将1级和2级的结果得到:

    TreeResult.Add("1,1,1", 1);
    TreeResult.Add("2,2,1", 2);
    TreeResult.Add("2,3,2", 1);

    我们还是自定义数据结构,key表示:层级,节点个数,叶子个数,value表示这样的平衡树有几种情况

    因此我们可以这样构造一个递归函数:

    public static int cal(int n,int m,int level)
            {
                int result = 0;
                string key = "";
                key = level.ToString() + "," + n.ToString() + "," + m.ToString();
                string tmpkey="";
                if (TreeResult.ContainsKey(key))
                {
                    return TreeResult[key];
                }
                if (level < 3)
                {
                    TreeResult.Add(key, 0);
                    return 0;
                }
                int left = 0;
                int right = 0;
                int rightnode = 0;
                int rightleaf = 0;
                int count =0;


                if (m > dic[level][3] || m < dic[level][1])
                {
                    TreeResult.Add(key, 0);
                    return 0;
                }
                for (int i = level - 2; i <= level - 1; i++)
                {
                    for (int j = level - 2; j <= level - 1; j++)
                    {
                        if (i != level - 1 && j != level - 1)
                        {
                            continue;
                        }
                        for (int leftnode = dic[i][0]; leftnode <= dic[i][2]; leftnode++)
                        {
                            if (leftnode > n - 1)
                            {
                                break;
                            }
                            rightnode = n - 1 - leftnode;
                            for (int leftleaf = dic[i][1]; leftleaf <= dic[i][3]; leftleaf++)
                            {
                                if (leftleaf > m)
                                {
                                    break;
                                }
                                rightleaf = m - leftleaf;
                                if (rightleaf <= 0)
                                {
                                    break;
                                }
                                tmpkey=i.ToString() + "," + leftnode.ToString() + "," + leftleaf.ToString();
                                if (!TreeResult.ContainsKey(tmpkey))
                                {
                                   
                                    left = cal(leftnode, leftleaf, i);
                                    if (!TreeResult.ContainsKey(tmpkey))
                                    {
                                        TreeResult.Add(tmpkey, left);
                                    }
                                }
                                else
                                {
                                    left = TreeResult[tmpkey];
                                }

                                tmpkey = j.ToString() + "," + rightnode.ToString() + "," + rightleaf.ToString();
                                if (!TreeResult.ContainsKey(tmpkey))
                                {
                                    right = cal(rightnode, rightleaf, j);
                                    if (!TreeResult.ContainsKey(tmpkey))
                                    {
                                        TreeResult.Add(tmpkey, right);
                                    }
                                }
                                else
                                {
                                    right = TreeResult[tmpkey];
                                }
                                count += left * right;
                            }
                        }
                    }
                }

                if (!TreeResult.ContainsKey(key))
                {
                    TreeResult.Add(key, count );
                }
                result = count;
                return result;
            }

    表示对于n个节点,m个叶子,在level层级下有多少种符合条件的平衡二叉树

    在level层级降级过程,还需要考虑n,m如何分配给左右子树各多少个,由于有了前面的范围集合字典,我们可以遍历范围内的节点和叶子个数,超出范围的表示不可能出现,直接返回0

     

    ok,大功告成,当输入n,我们首先判断有n个节点的平衡二叉树可能出现在哪些层级范围内,然后调用cal函数就可以了,累加得到结果。

    由于题目说了n<=20,所以在前面,我们的字典只构造了6级

     

    提交代码,通过。

     

     

  • 1 0
    原创粉丝点击