菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
447
0

面试笔试总结——二叉树

原创
05/13 14:22
阅读数 78917

收集整理一些关于二叉树的笔试面试题。

二叉树的数据结构:

struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
};

1. 二叉树的深度

最简单的方法便是递归法。

int TreeDepth(TreeNode *proot)
{
    if(!pRoot) return 0;
    return max(1+TreeDepth(pRoot->left), TreeDepth(pRoot->right));
}

 

2. 二叉树的遍历

这里仅给出中序遍历。

2.1 非递归遍历

思路:对于任一结点P,

 1) 若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;
 2) 若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;
 3) 直到P为NULL并且栈为空则遍历结束。

void inOrder(TreeNode* root)     
{
    stack<TreeNode*> s;
    TreeNode *p=root;
    while(p!=NULL||!s.empty())
    {
        while(p!=NULL)
        {
            s.push(p);
            p=p->left;
        }
        if(!s.empty())
        {
            p=s.top();
            cout<<p->val<<" ";
            s.pop();
            p=p->right;
        }
    }    
}

2.2 递归遍历

void inOrder(TreeNode* root)     
{
    if(root!=NULL)
    {
        inOrder(root->left);
        cout<<root->val<<" ";
        inOrder(root->right);
    }
}

 

3. 二叉树的层序遍历

将遍历的结果放入vector中。

vector<int> PrintFromTopToBottom(TreeNode* root) {
    vector<int> vec;
    if(root==nullptr) return vec;  //指针推荐这种写法 布尔值这样写:if(!root) 
    queue<TreeNode*> Q ;
    TreeNode* p = nullptr;
   
    Q.push(root);
    while(!Q.empty()){          //empty()返回布尔值 所以这样写
        p = Q.front();
        Q.pop();
        vec.push_back(p->val);
        if(p->left != nullptr) 
            Q.push(p->left);
        if(p->right != nullptr)
            Q.push(p->right);
    }
    return vec;
}

延伸:二叉树层序遍历,将树的每一层的结果保存为一行。

vector<vector<int> > Print(TreeNode* pRoot) {
    vector<vector<int> > res;
    if(pRoot==nullptr) return res;
    queue<TreeNode*> q;
    q.push(pRoot);
    
    while(!q.empty())
    {
        int lo = 0, hi = q.size();  //使用lo和hi提取行号
        vector<int> c;
        while(lo++ < hi)
        {
            TreeNode *t = q.front();
            q.pop();
            c.push_back(t->val);
            if(t->left) q.push(t->left);
            if(t->right) q.push(t->right);
        }
        res.push_back(c);
    }
    return res;
}

 

4. 求二叉树的镜像

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

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);
} 

延伸:判断两个二叉树是否对称,即其中一个是否是另一个的镜像。

思路:

/*首先根节点以及其左右子树,左子树的左子树和右子树的右子树相同
* 左子树的右子树和右子树的左子树相同即可,采用递归
* 非递归也可,采用栈或队列存取各级子树根节点
*/

bool isSymmetrical(TreeNode* pRoot)
{
    return isSymmetrical(pRoot,pRoot);
}

bool isSymmetrical(TreeNode* pRoot1, TreeNode* pRoot2)
{
    if(pRoot1==NULL && pRoot2==NULL)
        return true;
    if(pRoot1==NULL ||  pRoot2==NULL)
        return false;
    if(pRoot1->val != pRoot2->val)
        return false;
    return isSymmetrical(pRoot1->left, pRoot2->right) && isSymmetrical(pRoot1->right, pRoot2->left);
}

 

5. 给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8)    中,按结点数值大小顺序第三小结点的值为4

    int count = 0;
    TreeNode* KthNode(TreeNode* pRoot, int k)
    {
        if(pRoot){
            TreeNode* ret = KthNode(pRoot->left,k);
            if(ret) return ret;   //此判断为了确保在找到(count == k)的时候能逐层返回
            if(++count==k) return pRoot;
            ret = KthNode(pRoot->right,k);
            if(ret) return ret;
        }
        return nullptr;
    }

 

6. 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

public class TreeLinkNode {
    int val;
    TreeLinkNode left = null;
    TreeLinkNode right = null;
    TreeLinkNode next = null;

    TreeLinkNode(int val) {
        this.val = val;
    }
}

分析二叉树的下一个节点,一共有以下情况:

1.二叉树为空,则返回空;
2.节点右孩子存在,则设置一个指针从该节点的右孩子出发,一直沿着指向左子结点的指针找到的叶子节点即为下一个节点;
3.节点不是根节点。如果该节点是其父节点的左孩子,则返回父节点;否则继续向上遍历其父节点的父节点,重复之前的判断,返回结果。
public TreeLinkNode GetNext(TreeLinkNode pNode)
{
    if(pNode == null) return null;
    if(pNode.right!=null){   //如果有右子树,则找右子树的最左节点
        pNode = pNode.right;
        while(pNode.left!=null) 
            pNode = pNode.left;
        return pNode;
    }
    
    while(pNode.next!=null){
       //没有右子树,如果该节点是其父节点的左孩子,则返回父节点;
       //否则继续向上遍历其父节点的父节点,重复之前的判断,返回结果。
        if(pNode.next.left==pNode) 
            return pNode.next;
        pNode = pNode.next;
    }
    return null;
}        

 

发表评论

0/200
447 点赞
0 评论
收藏