【剑指offer】二叉树:层次遍历存一维数组,层次遍历存二维数组,求深度(递归,非递归),前序中序求后序,求镜像,判断子树

1.从上往下打印出二叉树的每个节点,同层节点从左至右打印:

这个题,用一个队列来做。为什么队列,因为队列先进先出的特性,满足二叉树层次输出。

class Solution {
public:
    vector<int> PrintFromTopToBottom(TreeNode* root) 
    {
        vector<int> vec;
        if(NULL == root) return vec;
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty())
        {
            TreeNode* head = que.front();
            if(head->left != NULL)
            {
                que.push(head->left);
            }
            if(head->right != NULL)
            {
                que.push(head->right);
            }
            vec.push_back(head->val);
            que.pop();
        }
        return vec;
        
    }
};

2.输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

class Solution {
public:
    int NodeNumber;
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) 
    {
        if(pre.size() != vin.size()) return NULL;
        NodeNumber = pre.size();
		int* ps = new int[pre.size()+1];
		for(int i = 0;i<=NodeNumber;i++)
		{
			ps[i] = pre[i];
		}
		
		int* is = new int[vin.size()+1];
		for(int i = 0;i<=NodeNumber;i++)
		{
			is[i] = vin[i];
		}
        TreeNode *s = Create(ps,is,NodeNumber);
		return s;
    }
    
   TreeNode* Create(int* ps,int* is,int n)  //前序数组+中序数组-->后序
    {
        TreeNode *s = NULL;  
        if(n > 0)
        {
            s = new TreeNode(ps[0]);
            int pos = FindPos(is,ps[0],n);
            if(pos == -1)
            {
                exit(-1);
            }
            s->left= Create(ps+1,is,pos);
            s->right = Create(ps+pos+1,is+pos+1,n-pos-1);
        }
        return s;
    }
    
    int FindPos(int*is,int x,int n)
    {
        int pos = -1;
        for(int i = 0;i < n;i++)
        {
            if(is[i] == x)
            {
                pos = i;
                break;
            }
        }
        return pos;
    }
};

3.输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。

方法一:递归做法

int TreeDepth(TreeNode* pRoot)
    {
        if(pRoot == NULL ) {
            return 0;
        }
        else{
           int left = TreeDepth(pRoot->left);
           int right = TreeDepth(pRoot->right);
           return left > right ? left +1 : right +1;
        }
    }

方法二:利用层次遍历。想一下我们之前都可以层次遍历了,那么遍历到第几层,该二叉树就有几层:
如图将一个二叉树入队,在每一层前加一个标记,最后出队时计算有几个标记。

最后标记个数-1 就是二叉树的层数

代码:

int TreeDepth(TreeNode* pRoot)
    {
        if(pRoot == NULL ) return 0;
        int counter = 0;//计数器
        queue<TreeNode*> que;
        que.push(NULL);
        que.push(pRoot);
        
        while(!que.empty())
        {
            TreeNode* p = que.front();
            if(p == NULL)
            {
                counter++;
                que.pop();
                if(que.empty())//这里要判断空,要考虑最后队列中只剩下一个的NULL,如果不判断就无限循环了
                {
                    break;
                }
                que.push(NULL);
                continue;
            }
            else
            {
                if(p->left != NULL)
                {
                    que.push(p->left);
                }
                if(p->right != NULL)
                {
                    que.push(p->right);
                }
                que.pop();
            }
        }
        return (counter - 1) ;
    }

4.从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

牛客中题目的返回值是一个二维vector数组

这道题和上一个层次遍历一户一样,只是上一个层次遍历求的是层数,这个层次遍历将每层的结果放在二维数组中,本体也学会了动态的使用二维数组vector

上图依旧可用:

代码:

//那个while(!que.empty()) 中的判断条件没用啊,感觉应该写成while(1) 退出条件在代码中 ,,,额,,,

vector<vector<int> > Print(TreeNode* pRoot) 
        {
            vector<vector<int>> mat;
            if(pRoot == NULL) return mat;
            
            queue<TreeNode*> que;
            que.push(NULL);
            que.push(pRoot);
            while(!que.empty())
            {
                TreeNode* p = que.front();
                if(p == NULL)//说明二维数组需要添加一个行了
                {
                    mat.push_back(vector<int>());
                    que.pop();
                    if(que.empty()) break;
                    que.push(NULL);
                }
                else
                {
                    if(p->left != NULL)
                    {
                        que.push(p->left);
                    }
                    if(p->right != NULL)
                    {
                        que.push(p->right);
                    }
                    int size = mat.size();
                    mat[size-1].push_back(p->val);
                    que.pop();
                }
            }
            mat.pop_back();//这里最后要pop_back一下,不然会多一行没有数据的
            return mat;
        }

5.操作给定的二叉树,将其变换为源二叉树的镜像。

方法一:很容易想到用递归去解决:

void Mirror(TreeNode *pRoot)
      {
        if(pRoot == NULL) return;
        
        TreeNode *tmp = pRoot->left;
        pRoot->left = pRoot->right;
        pRoot->right = tmp;
        
        Mirror(pRoot->left);
        Mirror(pRoot->right);
    }

6.输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

这个题,真的是,将递归的思想发挥到极致.......

HasSubTree:有子树

IsSubTree:是子树

所以Has有3种情况:Is,左子树Has,右子树Has

代码:
 

class Solution {
public:
    bool IsSubTree(TreeNode* pRoot1, TreeNode* pRoot2)
    {
        
        if(pRoot2 == NULL) return true;  //这里要return true,说明是子树的情况下遍历完所有的结点了,子树该赶回结果了 
        if(pRoot1 == NULL) return false; //这句判断 如果上面的判断之前,就错了。。。找了好久的错误
        if(pRoot1->val == pRoot2->val)
        {
            return IsSubTree(pRoot1->left,pRoot2->left) && IsSubTree(pRoot1->right,pRoot2->right);
        }
        else    
            return false;
    }
    bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)//有子树
    {
        if(pRoot1 == NULL || pRoot2 == NULL ) return false;
        return IsSubTree(pRoot1,pRoot2) || HasSubtree(pRoot1->left,pRoot2) || HasSubtree(pRoot1->right,pRoot2);
    }
};

7.输入一棵二叉树,判断该二叉树是否是平衡二叉树。

思路:求出结点的左右子树的深度,判断两个深度相减绝对值 > 1,大于1返回false,否则返回左子树的左右子树和右子树的左右子树

代码:

int TreeDepth(TreeNode* pRoot)
    {
        if(pRoot == NULL ) return 0;
        int counter = 0;//计数器
        queue<TreeNode*> que;
        que.push(NULL);
        que.push(pRoot);
        
        while(!que.empty())
        {
            TreeNode* p = que.front();
            if(p == NULL)
            {
                counter++;
                que.pop();
                if(que.empty())//这里要判断空,要考虑最后队列中只剩下一个的NULL,如果不判断就无限循环了
                {
                    break;
                }
                que.push(NULL);
                continue;
            }
            else
            {
                if(p->left != NULL)
                {
                    que.push(p->left);
                }
                if(p->right != NULL)
                {
                    que.push(p->right);
                }
                que.pop();
            }
        }
        return (counter - 1) ;
    }
    bool IsBalanced_Solution(TreeNode* pRoot) 
    {
        if(pRoot == NULL) return true;
        if(abs(  TreeDepth(pRoot->left) - TreeDepth(pRoot->right)) > 1  )
        {
            return false;
        }
        else
        {
            return IsBalanced_Solution(pRoot->left) && IsBalanced_Solution(pRoot->right);
        }
    }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值