牛客网算法教程-中级篇-第二章

1.青草游戏-博弈


分析:
这是一道博弈题,题目背后就是数学思想。我们这里可以不深究内部的数学思想,只通过规律来求解

1.0-5这个情况我们可以简单分析
2.当我们niu吃完了草之后,递归调用这个算法。比如说,现在有6的草,牛牛先吃1,然后剩余5。然后5是yang赢了,所以niu赢了。是不是很烧脑?
3.简单来说,第二轮的先手,是第一轮的后手。所以,在递归进去的时候,就是出现了身份互换。所以在递归里面,yang赢了,就是代表niu赢了。


4.但是这个算法递归深度太深,所以只能对100以内的使用。

using System;
namespace test
{
    class test
    {
        static void Main()
        {
            int count = Convert.ToInt32(Console.ReadLine());

            for (int i = 0; i < count; i++)
            {
                Console.WriteLine(Win(Convert.ToInt32(Console.ReadLine())));
            }
        }

        static string Win(int n)
        {
            if (n <= 5)
            {
                if (n == 2 || n == 5|| n==0 )
                {
                    return "yang";
                }
                else
                {
                    return "niu";
                }
            }
            int cur = 1;
            while (cur <= n)
            {
                if (Win(n - cur) == "yang")
                {
                    return "niu";
                }
                if (cur > n / 4) break;

                cur *= 4;
            }

            return "yang";
        }
    }
}

5.但是,我们可以总结出规律,temp % 5 == 0 || temp % 5 == 2的时候是yang赢,其他情况是niu赢
6.所以,以后玩博弈,记得做先手!!!
在这里插入图片描述

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _013
{
    class Program
    {
        static void Winner()
        {
            int n = Int32.Parse(Console.ReadLine());
            long[] arr = new long[n];
            for(int i = 0; i < n; i++)
            {
                arr[i] = Int32.Parse(Console.ReadLine());              
            }
            foreach(long temp in arr)
            {
                if (temp % 5 == 0 || temp % 5 == 2)
                {
                    Console.WriteLine("yang");
                }
                else
                {
                    Console.WriteLine("niu");
                }
            }
        }
        static void Main(string[] args)
        {
            Winner();
            Console.ReadKey();
        }
    }
}

2.正方形染色-预处理

在这里插入图片描述
在这里插入图片描述
分析:
题目的意思是,让左边全部都是R(最少一个),右边全部是G
具体情况呢,并不是说让R左移,G右移
不是说开始有多少个R,结束就得有多少个R
只需要涂最少的色,让仅剩的R在左边,G全部在右边
这里就用到了预处理!
1.什么是预处理?就是提前将我们后面计算需要的东西进行准备
2.在这里,我们就是用分界线的方式,去遍历每个位置
3.首先,我们一个for循环,将left数组进行初始化。这就是我们的预处理。我们left数组,记录的就是当前位置i,左边的R个数。Right记录的是放弃
在这里插入图片描述

using System;
namespace test
{
    class test
    {
        static void Main()
        {
            string arr = Console.ReadLine();
            int min = 100000;
            int[] left = new int[arr.Length];
            int[] right = new int[arr.Length];
            
            //left预处理
            for (int i = 0; i < arr.Length; i++)
            {
                if (arr[i] == 'G')
                {
                    if (i == 0)
                    {
                        left[i] = 1;
                    }
                    else
                    {
                        left[i] = left[i - 1] + 1;
                    }
                }
                else
                {
                    if (i == 0)
                    {
                        left[i] = 0;
                        continue;
                    }
                    left[i] = left[i - 1];
                }

            }
            //Right预处理
            for (int i = arr.Length - 1; i >= 0; i--)
            {
                if (arr[i] == 'R')
                {
                    if (i == arr.Length - 1)
                    {
                        right[i] = 1;
                    }
                    else
                    {
                        right[i] = right[i + 1] + 1;
                    }
                }
                else
                {
                    if (i == arr.Length - 1)
                    {
                        right[i] = 0;
                        continue;
                    }
                    right[i] = right[i + 1];
                }

            }

            //遍历索引
            for (int i = 0; i < arr.Length; i++)
            {
                if(i == arr.Length - 1)
                {
                    min = Math.Min(left[i], min);
                    break;
                }
                if (i == 0)
                {
                    min = Math.Min(right[i], min);
                    continue;
                }
                
                //最小染色块数,就是将左边的G全部染成R,右边的R全部染成G
                min = Math.Min(left[i] + right[i+1], min);
            }
            Console.WriteLine(min);
        }
    }
}

3.边框全1最大正方形大小 -预处理

牛客网连接
在这里插入图片描述
在这里插入图片描述
分析:
首先我们来对可能的正方形个数来进行判断
在这里插入图片描述
综上,我们可以知道,最多有N的三次方个正方形
那么,我们的时间复杂度是N的三次方,但是,我们在遍历这N的三次方个正方形的时候,我们还得对其进行判断。即,以a点作为左上方点时,最大的正方形边长是多少?这里就需要遍历,那么总的时间复杂度就是N的四次方了现在
那么,我们可以优化吗?
可以,预处理。
我们提前将当前位置下面和右边所以的1的长度,进行记录。等我们到i位置的时候,我们就可以轻松的知道,我的右边有多少个1,下面有多少个1,能不能组成一个正方形了!
1.我们定义一个和Matrix一样大的R矩阵,专门用来记录i,j位置右边1的个数。然后是D矩阵,专门记录i,j位置下面1的个数
2.我们只需要在几个特殊的位置判断即可。即找出D,R中小的那个,作为边长。然后去边的另外的一个顶点,去判断边的长度是不是也是指定边的长度。最后去判断i+边长,j+边长的位置,是不是1
在这里插入图片描述
3.但是有特殊情况,比如说下面。我们就算拿到了R和D中比较小的边,但是这个边也不是我们要找的正方形的边。所以在这里,我们对边长len需要进行逐一判断,比如len一开始是40。那么我们就对39,38,39…一直到长度2进行判断即可。
在这里插入图片描述
在这里插入图片描述

using System;
namespace test{
    class test{
        static void Main(){
            int len=Convert.ToInt32( Console.ReadLine());
            
            int[,] Matrix=new int[len,len];
            int[,] MatrixR=new int[len,len];
            int[,] MatrixD=new int[len,len];
            for(int i=0;i<len;i++){
                string[] getin=Console.ReadLine().Split(' ');
                for(int j=0;j<len;j++){
                    Matrix[i,j]=Convert.ToInt32(getin[j]);
                }
            }
            
            //初始化R
            for(int i=0;i<len;i++){
                for(int j=len-1;j>=0;j--){
                    if(Matrix[i,j]==1){
                        if(j==len-1){
                            MatrixR[i,j]=1;
                        }else{
                            MatrixR[i,j]=MatrixR[i,j+1]+1;
                        }
                    }else{
                        MatrixR[i,j]=0;
                    }
                }
            }
            
            //初始化D
            for(int i=0;i<len;i++){
                for(int j=len-1;j>=0;j--){
                    if(Matrix[j,i]==1){
                        if(j==len-1){
                            MatrixD[j,i]=1;
                        }else{
                            MatrixD[j,i]=MatrixD[j+1,i]+1;
                        }
                    }else{
                        MatrixD[j,i]=0;
                    }
                }
            }
            
            int Max=0;
            //遍历Matrix
            for(int i=0;i<len;i++){
                for(int j=0;j<len;j++){
                    if(Matrix[i,j]==1){
                        //如果此时R和D都有2以上
                        if(MatrixR[i,j]>1&&MatrixD[i,j]>1){
                            int min=Math.Min(MatrixR[i,j], MatrixD[i,j]);
                            //这里是做长度的遍历
                            while(min>=2){
                                if(MatrixR[i+min-1,j]>=min && MatrixD[i,j+min-1] >=min ){
                                    if(Matrix[i+min-1,j+min-1]==1){
                                        Max=Math.Max(min, Max);
                                        break;
                                    }           
                                }else{
                                    min--;
                                }
                            }
                        }
                    }
                }
            }
            Console.WriteLine(Max);
        }
    }
}

4.已知先序和中序求后序 -二叉树

牛客网链接
在这里插入图片描述
解析:
我们总结得如下规律
1.首先前序遍历的根节点在L1位置,然后这个根节点在中序遍历的中间位置,在后序遍历的结束位置,那么我们可以根据根节点在中序遍历的位置,推出我们子树的长度
2.知道子树长度之后,我们就可以将数组拆成“根节点-左子树-右子树”的模式,
然后我们分别对子树进行递归,即可!
在这里插入图片描述
在这里插入图片描述

using System;
using System.Collections.Generic;

namespace test
{
    class test
    {
        static Dictionary<int, int> iniDic = new Dictionary<int, int>();
        static int len = 0;
        static void Main()
        {
            len = Convert.ToInt32(Console.ReadLine());
            int[] pre = new int[len];
            int[] ini = new int[len];
            int[] pos = new int[len];

            string[] prein = Console.ReadLine().Split(' ');
            for (int i = 0; i < len; i++)
            {
                pre[i] = Convert.ToInt32(prein[i]);
            }
            string[] iniin = Console.ReadLine().Split(' ');
            for (int i = 0; i < len; i++)
            {
                ini[i] = Convert.ToInt32(iniin[i]);
                //存到字典里面,方便查找
                iniDic.Add(ini[i], i);
            }


            SetPos(pre, 0, len - 1, ini, 0, len - 1, pos, 0, len - 1);

            for (int i = 0; i < len; i++)
            {
                Console.Write(pos[i] + " ");
            }


        }


        static void SetPos(int[] pre, int L1, int R1, int[] ini, int L2, int R2, int[] pos, int L3, int R3)
        {
            //如果前序遍历中的 子树长度小于1 即不存在 则返回
            if (L1 > R1)
            {
                return;
            }

            //找到根节点在中序遍历的位置
            int find = iniDic[pre[L1]];

            //计算子树节点个数
            int Count = find - L2;

            //赋值
            pos[R3] = pre[L1];


            //左树
            SetPos(pre, L1 + 1, L1 + Count,
                ini, L2, find - 1,
                pos, L3, L3 + Count - 1);

            //右树
            SetPos(pre, L1 + Count + 1, R1,
                ini, find + 1, R2,
                pos, L3 + Count, R3 - 1);
        }

    }
}

5.二叉树权值和最大路径 -二叉树左右信息归纳

牛客网链接
在这里插入图片描述
在这里插入图片描述
分析:
1.我们想要获取最大路径的话,我们只需要获取左子树和右子树的最大路径,将其中较大的加上自己然后返回即可
2.然后左子树又去获取自己的左子树,一直循环往复,递归

在这里插入图片描述在这里插入图片描述

using System;
using System.Collections.Generic;
namespace test
{
    class test
    {
        static int len = 0;
        static void Main()
        {
            len = Convert.ToInt32(Console.ReadLine());
            int[,] arr = new int[len, 2];
            for (int i = 0; i < len; i++)
            {
                string[] putin = Console.ReadLine().Split(' ');
                arr[i, 0] = Convert.ToInt32(putin[0]);
                arr[i, 1] = Convert.ToInt32(putin[1]);
            }
            Console.WriteLine(GetBig(arr, 1));
        }
        //获取最大路径
        static int GetBig(int[,] arr, int index)
        {
            if (index < 0) return 0;
            //左子树中最大路径的值
            int leftinfo = GetBig(arr, GetLeft(arr, index));
            //右子树中最大路径的值
            int rightinfo = GetBig(arr, GetRight(arr, index));

            //判断左边大还是右边大
            int p1 = 0;
            int p2 = 0;
            if (leftinfo != 0)
            {
                //左边有树
                p1 = arr[index - 1, 0] + leftinfo;
            }
            if (rightinfo != 0)
            {
                //右边有树
                p2 += arr[index - 1, 0] + rightinfo;
            }
            if (leftinfo != 0 && leftinfo != 0)
            {
                return Math.Max(p1, p2);
            }
            if (leftinfo == 0 && leftinfo == 0)
            {
                return arr[index - 1, 0];
            }

            return leftinfo == 0 ? p1 : p2;
        }
        //获取左节点
        static int GetLeft(int[,] arr, int index)
        {
            for (int i = 1; i < len; i++)
            {
                if (arr[i, 1] == index)
                {
                    return i + 1;
                }
            }
            return -1;
        }
        //获取右节点
        static int GetRight(int[,] arr, int index)
        {
            int count = 0;
            for (int i = 1; i < len; i++)
            {
                if (arr[i, 1] == index)
                {
                    count += 1;
                    if (count == 2)
                    {
                        return i + 1;
                    }
                }
            }
            return -1;
        }

    }
}

二叉树递归总结

1.在节点可以向左树和右树要info的设定下,头结点应该如何组织可能性?
2.组织可能性看到底要向左子树和向右子树要什么info
3.左info+右info==总info

这道题就是就是头结点需要向左、右子树要最大路径,然后推出总的最大路径

6.二叉树结构计数

牛客网链接
在这里插入图片描述
分析:
1.我们当前节点需要从左右子树获取什么信息?节点数
2.比如说1,左子树有三个,右子树有三个,那么总的情况有多少种?答案是二十五种,5*5=25

5

在这里插入图片描述
3.那么,我们只需要一直枚举下去就行了。比如说,节点数是7,那么子树是6。那么就要0,6 1,5 2,4 3,3 4,2 5,1 6,0 六种情况,我们全部加起来即可!
在这里插入图片描述

using System;
namespace test{
    class test{
        static void Main(){
            int Count=Convert.ToInt32( Console.ReadLine());
            
            Console.WriteLine(NumTrees(Count));            
        }
        static long NumTrees(int n){
            if(n<2)return 1;
            long[] dp=new long[n+1];
            //MOD有什么用? 下面有解释
            long MOD=1000000007;
            dp[0]=1;
            for(int i=1;i<n+1;i++){
                //计算节点个数为i的时候的dp值
                //需要将左子树长度从0到i情况都枚举一次
                for(int j=1;j<i+1;j++){
                    //左子树个数的dp*右子树个数的dp
                    dp[i]+=dp[j-1]*dp[i-j];
                    //防止溢出int32位长度
                    dp[i]%=MOD;
                }
            }
            
            return dp[n];
        }
    }
}

对1000000007取模?

大数阶乘,大数的排列组合等,一般都要求将输出结果对1000000007取模
为什么总是1000000007呢?

1、大数求余原因:大数越界
大数越界:随着n增大,f(n)会超过Int32甚至Int64的取值范围,导致最终的返回值错误。
当一个问题只对答案的正确性有要求,而不在乎答案的数值,可能会需要将取值很大的数通过求余变小。

2.int32位取值范围是-2147483648~2147483647,1000000007 是最小的十位质数。模1000000007,可以保证值永远在int的范围内。

3.int64位的最大值为2^63-1,对于1000000007来说它的平方不会在int64中溢出
所以在大数相乘的时候,因为(a∗b)%c=((a%c)∗(b%c))%c,所以相乘时两边都对1000000007取模,再保存在int64里面不会溢出

7.搜索二叉树转双向链表-二叉树左右信息归纳

牛客网链接
在这里插入图片描述
在这里插入图片描述
分析:
1.我们需要将一棵树,按双向链表进行输出,其实就是中序遍历,难点是如何将指针串起来,因为是要返回头指针,然后去遍历头指针
2.其实这里可以骗测试用例,直接按中序输出树即可。还有更粗暴的,for循环输出1到节点树,比如123456789!实测有效
3.但是,我们肯定也不可以这样做
4.在这里,就要用到递归的思想了。我们需要什么信息?从左子树和右子树拿什么信息?这里,我们可以构造一个新的数据结构,帮助我们来解决
5.一个TreeNode,里面只有两个Node,一个表示begin的Node,一个表示end的Node。begin是已经和end这两个Node内部其实是已经连起来了
在这里插入图片描述
6.那么我们将左子树的这个TreeNode的结果,和右子树的TreeNode的结果同时给父节点。那么父节点再把这两个TreeNode连接起来,就构成了一个新的TreeNode
7.不断的连接,最后构造出全部的节点连接
8.结束时的TreeNode的begin的Node,已经和end的Node,指针连起来了
9.核心思想就是每个节点,拿自己左子树的TreeNode和右子树的TreeNode,生成自己的TreeNode
在这里插入图片描述


using System;
using System.Collections.Generic;
using System.Text;

namespace test
{
    class test
    {
        public class TreeNode
        {
            public Node begin;
            public Node end;

            public TreeNode(Node begin, Node end)
            {
                this.begin = begin;
                this.end = end;
            }
        }
        public class Node
        {
            public int val;
            public Node left;
            public Node right;
            public Node()
            {
            }
            public Node(int val)
            {
                this.val = val;
            }

        }

        static Dictionary<int, Node> nodes = new Dictionary<int, Node>();
        static void Main()
        {
            int len = Convert.ToInt32(Console.ReadLine());
            Node nodehead = new Node(0);

            //构造双链表二叉树
            for (int i = 0; i < len; i++)
            {
                string[] getin = Console.ReadLine().Split(' ');
                int val = Convert.ToInt32(getin[0]);
                int left = Convert.ToInt32(getin[1]);
                int right = Convert.ToInt32(getin[2]);
                Node node;


                if (!nodes.ContainsKey(val))
                {
                    node = new Node(val);
                    nodes.Add(val, node);
                }
                else
                {
                    node = nodes[val];
                }


                if (i == 0)
                {
                    nodehead = node;
                }

                if (!nodes.ContainsKey(left)&& left != 0)
                {
                    Node nodeleft = new Node(left);
                    nodes.Add(left, nodeleft);
                    node.left = nodeleft;
                }
                else if(left != 0)
                {
                    node.left = nodes[left];
                }

                if (!nodes.ContainsKey(right)&&right!=0)
                {
                    Node noderight = new Node(right);
                    nodes.Add(right, noderight);
                    node.right = noderight;
                }
                else if(right != 0)
                {
                    node.right = nodes[right];
                }
            }

            nodes.Clear();

            Node beginNode = GetTreeNode(nodehead).begin;
            StringBuilder stringBuilder = new StringBuilder();
            while (beginNode != null)
            {
                stringBuilder.Append(beginNode.val + " ");
                beginNode = beginNode.right;

            }
            Console.WriteLine(stringBuilder);
        }


        static TreeNode GetTreeNode(Node node)
        {
            if (node==null)
            {
                return new TreeNode(null, null);
            }
            TreeNode leftTreeNode = GetTreeNode(node.left);
            TreeNode rightTreeNode = GetTreeNode(node.right);

            //现在在某个节点Node上


            //如果leftTreeNode的end节点不为空
            //则让end节点Node的right指针指向当前的节点
            if (leftTreeNode.end != null)
            {
                leftTreeNode.end.right = node;
            }
            //修改Node的左右指针
            node.left = leftTreeNode.end;
            node.right = rightTreeNode.begin;


            //如果在这之前的rightTreeNode的end节点不为空
            //则让begin节点Node的left指针指向当前的节点
            if (rightTreeNode.begin != null)
            {
                rightTreeNode.begin.left = node;
            }

            return new TreeNode(
                //如果左边begin是空的,则返回当前节点作为begin
                leftTreeNode.begin != null ? leftTreeNode.begin : node,
                //如果右边end是空的,则返回当前节点作为end
                rightTreeNode.end != null ? rightTreeNode.end : node
                               );
        }
    }
}

8.最大搜索二叉子树节点数-二叉树左右信息归纳

牛客网链接
在这里插入图片描述

分析:
1.我们先看二叉树的解题思路
2.然后我们分析这道题是X有关还是X无关
3.我们根据左树和右树的信息推出当前数的信息
4.不断递归
在这里插入图片描述
在这里插入图片描述

using System;
using System.Collections.Generic;
namespace test
{
    class test
    {

        public class Info
        {
            public int MaxBSTsize;//最大搜索二叉树的大学
            public int Max;  //树最大值
            public int Min;  //树最小值
            public bool IsAllBst;
            public Info(int MaxBSTsize, int Max, int Min, bool IsAllBst)
            {
                this.MaxBSTsize = MaxBSTsize;
                this.Max = Max;
                this.Min = Min;
                this.IsAllBst = IsAllBst;
            }
        }

        public class Node
        {
            public int val;
            public Node left;
            public Node right;
            public Node(int val, Node left, Node right)
            {
                this.val = val;
                this.left = left;
                this.right = right;
            }
        }

        static Dictionary<int, Node> dics = new Dictionary<int, Node>();

        static void Main()
        {
            int len = Convert.ToInt32(Console.ReadLine().Split(' ')[0]);
            Node head = new Node(0, null, null);
            for (int i = 0; i < len; i++)
            {
                string[] putin = Console.ReadLine().Split(' ');
                int val = Convert.ToInt32(putin[0]);
                int left = Convert.ToInt32(putin[1]);
                int right = Convert.ToInt32(putin[2]);

                Node node;

                if (dics.ContainsKey(val))
                {
                    node = dics[val];
                }
                else
                {
                    node = new Node(val, null, null);
                    dics.Add(val, node);
                }
                if (i == 0)
                {
                    head = node;
                }

                if (left != 0)
                {
                    if (dics.ContainsKey(left))
                    {
                        node.left = dics[left];
                    }
                    else
                    {
                        Node nodeleft = new Node(left, null, null);
                        node.left = nodeleft;
                        dics.Add(left, nodeleft);
                    }
                }

                if (right != 0)
                {
                    if (dics.ContainsKey(right))
                    {
                        node.right = dics[right];
                    }
                    else
                    {
                        Node noderight = new Node(right, null, null);
                        node.right = noderight;
                        dics.Add(right, noderight);
                    }
                }
            }
            //Console.WriteLine(head.val+" "+head.left.val);
            int Mmax = GetInfo(head).MaxBSTsize;
            Console.WriteLine(Mmax);

        }

        static Info GetInfo(Node x)
        {
            if (x == null)
            {
                return null;
            }
            Info leftInfo = GetInfo(x.left);
            Info rightInfo = GetInfo(x.right);

            //拿到左边和右边的info之后,生成当前节点的info

            int XmaxBSTsize = 0;
            bool XisBst = false;


            //左边和右边的最大搜索二叉树的值
            int p1 = -1;
            int p2 = -1;
            if (leftInfo != null)
            {
                p1 = leftInfo.MaxBSTsize;
            }
            if (rightInfo != null)
            {
                p2 = rightInfo.MaxBSTsize;
            }

            //新的最大搜索二叉树的值
            int p3 = -1;
            //
            if (
               //左树是不是最大搜索二叉树
               (leftInfo == null ? true : leftInfo.IsAllBst)
               &&

               //右树是不是最大搜索二叉树
               (rightInfo == null ? true : rightInfo.IsAllBst)
               &&
                //左子树的最大值是不是小于X
                (leftInfo == null ? true : leftInfo.Max < x.val)
                &&
                 //右子树的最小值是不是大于X
                 (rightInfo == null ? true : rightInfo.Min > x.val)
            )
            {

                //都满足的话,代表左右都是满足条件的树,现在将两个融合
                p3 = (leftInfo == null ? 0 : leftInfo.MaxBSTsize) +
                    (rightInfo == null ? 0 : rightInfo.MaxBSTsize) + 1;
                //当前节点是一个满足条件的树
                XisBst = true;
            }

            XmaxBSTsize = Math.Max(p1, Math.Max(p2, p3));

            //新的数的最大值和最小值
            int MaxVal = x.val;
            int MinVal = x.val;
            if (leftInfo != null)
            {
                MaxVal = Math.Max(leftInfo.Max, MaxVal);
                MinVal = Math.Min(leftInfo.Min, MinVal);
            }
            if (rightInfo != null)
            {
                MaxVal = Math.Max(rightInfo.Max, MaxVal);
                MinVal = Math.Min(rightInfo.Min, MinVal);
            }


            return new Info(XmaxBSTsize, MaxVal, MinVal, XisBst);

        }
    }
}

9.完全二叉树节点数-递归

牛客网链接
在这里插入图片描述
分析:
什么是完全二叉树?
完全二叉树是满二叉树的子集,意思就是,完全二叉树只可能小于等于满二叔的节点个数
同时,完全二叉树必须得是最后一层从左往右填的。

在这里插入图片描述

在这里插入图片描述

using System;
using System.Collections.Generic;

/*
public class TreeNode
{
	public int val;
	public TreeNode left;
	public TreeNode right;

	public TreeNode (int x)
	{
		val = x;
	}
}
*/

class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head TreeNode类 
     * @return int整型
     */
    public int nodeNum (TreeNode head) {
        //Console.WriteLine(124134134);
        if(head==null)return 0;
        return Bs(head,1,MostLeftLevel(head, 1));
        //return 1;
    }
    
    
    public static int Bs(TreeNode node,int level,int h){
        if(level==h)return 1;
        
        if((MostLeftLevel(node.right, level+1)==h)){
            //这里右树的最左深度一直,表示左树全为满
            return (1<<h-level)+Bs(node.right,level+1,h);
        }else{
            //左树并不满,右树为满
            return (1<<h-level-1)+Bs(node.left, level+1,h);
        }
    }
    public static int MostLeftLevel(TreeNode node,int level){
        while(node!=null){
            level++;
            node=node.left;
        }
        return level-1;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值