二叉树问题

      关于二叉树的笔试面试问题很多,涉及到深度遍历和广度遍历,以及相关路径搜索,树的重构,以及与二叉搜索平衡树相关的基础问题。。

94Binary Tree Inorder Traversal---考察二叉树中序遍历

题目描述:

Given a binary tree, return the inorder traversal of its nodes' values.

For example:
Given binary tree [1,null,2,3],

   1
    \
     2
    /
   3

return [1,3,2].

代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution 
{
public:
    void InorderTraverseBinaryTree(TreeNode* root, vector<int> &out)
    {
        if(root == NULL)
            return;
        // 向左走
        InorderTraverseBinaryTree(root->left, out);
        // 访问当前节点
        out.push_back(root->val);
        // 向右走
        InorderTraverseBinaryTree(root->right, out);
        return;
    }
    vector<int> inorderTraversal(TreeNode* root) 
    {
        vector<int> out;
        InorderTraverseBinaryTree(root, out);
        return out;
    }
};

98Validate Binary Search Tree---利用中序遍历判断

问题描述:

Given a binary tree, determine if it is a valid binary search tree (BST).

Assume a BST is defined as follows:

  • The left subtree of a node contains only nodes with keys less than the node's key.
  • The right subtree of a node contains only nodes with keys greater than the node's key.
  • Both the left and right subtrees must also be binary search trees.

Example 1:

    2
   / \
  1   3
Binary tree  [2,1,3] , return true.

Example 2:

    1
   / \
  2   3
Binary tree  [1,2,3] , return false.

问题解析:

1. 此题想要判断一颗二叉树是否是二叉搜索树,也就是说,一个节点其左子树的所有节点值都必须小于它,右子树的节点值都必须大于它的值。
2. 考虑到二叉搜索树的中序遍历是一个递增序列,因此采用中序遍历的解法来做。
3. 比较易懂的解法是:设置一个辅助数组,将中序遍历二叉树的结果存在辅助数组中,最后检查数组的是否是递增来判断是否是二叉搜索树。如下代码1,或者可以取消辅助数组,总是和中序遍历上一个值来比较,直到遍历结束,入代码二。

代码如下1:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
// 中序遍历二叉树
void InOrderTraverseBinaryTree(TreeNode* root, vector<int> &res)
{
    if(root == NULL)
        return;
    InOrderTraverseBinaryTree(root->left, res);
    res.push_back(root->val);
    InOrderTraverseBinaryTree(root->right, res);
    return;
}
class Solution 
{
public:
    // 判断是不是有效的二叉搜索树
    bool isValidBST(TreeNode* root) 
    {
        if(root == NULL)
            return true;
        vector<int> res;
        InOrderTraverseBinaryTree(root, res);
        if(res.size() < 2)
            return true;
        for(int i=1; i<res.size(); ++i)
        {
            if(res[i] <= res[i-1])
                return false;
        }
        return true;    
    }
};

代码如下2:

// 中序遍历二叉树
void InOrderTraverseBinaryTree(TreeNode* root, int &pre, bool &bIsPreExist, bool &bIsSerach)
{
    if(root == NULL)
        return;
    InOrderTraverseBinaryTree(root->left, pre, bIsPreExist, bIsSerach);
    if(!bIsPreExist)
    {
        // 采用bIsPreExist来标记当前的节点是否存在上一节点。
        bIsPreExist = true;
        pre = root->val;
    }
    else
    {
        // 保证中序遍历的时候每一个节点都比上一个节点的值大,才是二叉搜索树
        if(root->val <= pre)
        {
            bIsSerach = false;
            return;
        }
        pre = root->val;
    }
    InOrderTraverseBinaryTree(root->right, pre, bIsPreExist, bIsSerach);
    return;
}
class Solution {
public:
    // 判断是不是有效的二叉搜索树
    bool isValidBST(TreeNode* root) 
    {
        bool bIsPreExist = false;
        bool bIsSerach = true;
        int pre = 0;
        InOrderTraverseBinaryTree(root, pre, bIsPreExist, bIsSerach);
        return bIsSerach;    
    }
};


100Same Tree---利用树的遍历中任何一个均可以

问题描述:

Given two binary trees, write a function to check if they are the same or not.

Two binary trees are considered the same if they are structurally identical and the nodes have the same value.


Example 1:

Input:     1         1
          / \       / \
         2   3     2   3

        [1,2,3],   [1,2,3]

Output: true

Example 2:

Input:     1         1
          /           \
         2             2

        [1,2],     [1,null,2]

Output: false

 代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isSame(TreeNode* p, TreeNode* q)
    {
        if(p==NULL && q==NULL)
            return true;
        else if(p==NULL)
            return false;
        else if(q==NULL)
            return false;
        if(p->val != q->val)
            return false;
        return isSame(p->left, q->left) && isSame(p->right, q->right);
    }
    bool isSameTree(TreeNode* p, TreeNode* q) 
    {
        return isSame(p, q);
    }
};


101Symmetric Tree---利用树的遍历来解决

问题描述:

Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).

For example, this binary tree [1,2,2,3,4,4,3] is symmetric:

    1
   / \
  2   2
 / \ / \
3  4 4  3

But the following [1,2,2,null,3,null,3] is not:

    1
   / \
  2   2
   \   \
   3    3

问题解析:

1. 此题是判断一个二叉树是不是对称的二叉树,和上题解法类似。稍作改变。

代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool IsSymmetric(TreeNode *left, TreeNode *right)
    {
        if(left == NULL && right==NULL)
            return true;
        else if(left == NULL)
            return false;
        else if(right == NULL)
            return false;
        else
        {
            if(left->val != right->val) 
                return false;
            return  IsSymmetric(left->left, right->right) && IsSymmetric(left->right, right->left);
        }
    }
    bool isSymmetric(TreeNode* root) 
    {
        if(root == NULL)
            return true;
        
        return IsSymmetric(root->left, root->right);
    }
};


102Binary Tree Level Order Traversal---二叉树的层次遍历

问题描述:

Given a binary tree, return the  level order  traversal of its nodes' values. (ie, from left to right, level by level).

For example:
Given binary tree [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

return its level order traversal as:

[
  [3],
  [9,20],
  [15,7]
]


问题解析:

1. 二叉树的层次遍历,可以通过定义一个队列来实现层次遍历,化递归为循环。每次输出本层节点时,相应的把下层的节点压入队列中进行遍历。

代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    // 按照层次遍历
    vector<vector<int>> levelOrder(TreeNode* root) 
    {
        vector<vector<int>> out;
        if(root == NULL)
            return out;
        // 设置辅助队列
        deque<TreeNode*>de;
        de.push_back(root);
        int num = 1;
        int count = 0;
        
        vector<int> res;
        while(!de.empty())
        {
            ++count;
            res.push_back(de.front()->val);
            if(de.front()->left != NULL)
                de.push_back(de.front()->left);
            if(de.front()->right != NULL)
                de.push_back(de.front()->right);
            de.pop_front();
            if(count == num)
            {
                count = 0;
                out.push_back(res);
                res.clear();
                num = de.size();
            }
        }
        return out;
    }
};



103Binary Tree Zigzag Level Order Traversal--二叉树的Z字形层次遍历

问题描述:

Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between).

For example:
Given binary tree [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

return its zigzag level order traversal as:

[
  [3],
  [20,9],
  [15,7]
]

问题解析:

1. 此题相当于二叉树的变相的层次遍历,于之前不同的是,先按照由左至右,下一层按照由右至左,再下一层又按照由左至右的'Z'字形遍历。
2. 解决此题,可以利用两个栈sta1和sta2来解决。
     (1) 初始将root放在sta1里面,sta1中的每个结点,先遍历子结点的左结点,再遍历右结点,并将下层所有子结点置在sta2中。遍历一个结点,弹出一个结点,直到sta1为空。
     (2) 开始遍历sta2,sta2的栈弹出一个遍历一个顺序就是由右至左的顺序,这是sta2中每个结点按照由右至左的顺序遍历,并将下层子结点放在sta1中。直到sta2为空。
   (3)重复(1)和(2)的步骤,直到sta1和sta2为空。结束。

代码如下:

class Solution {
public:
    // 按照层次遍历,设置两个辅助栈来做
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) 
    {
        vector<vector<int>> out;
        if(root == NULL)
            return out;
        // 设置辅助栈
        stack<TreeNode*>sta1;
        stack<TreeNode*>sta2;
        sta1.push(root);
        int num = 1;
        int count = 0;
        bool bLeft=false;
        vector<int> res;
        while(!sta1.empty() || !sta2.empty())
        {
            while(!sta1.empty())
            {
                res.push_back(sta1.top()->val);
                if(sta1.top()->left != NULL)
                    sta2.push(sta1.top()->left);
                if(sta1.top()->right != NULL)
                    sta2.push(sta1.top()->right);
                sta1.pop();
            }
            if(!res.empty())
            {
                out.push_back(res);
                res.clear();
            }
            while(!sta2.empty())
            {
                res.push_back(sta2.top()->val);
                if(sta2.top()->right != NULL)
                    sta1.push(sta2.top()->right);
                if(sta2.top()->left != NULL)
                    sta1.push(sta2.top()->left);
                sta2.pop();
            }
            if(!res.empty())
            {
                out.push_back(res);
                res.clear();
            }
        }
        return out;
    }
};

104Maximum Depth of Binary Tree---求二叉树的深度

题目解析:

1. 此题是求一个二叉树的最大深度,指的是从根节点到其最远叶节点的层数。
2. 利用二叉树的深度遍历很快能够求出,代码如下:

代码如下:

class Solution {
public:
    int maxDepth(TreeNode* root) 
    {
        if(root == NULL)
            return 0;
        int left = maxDepth(root->left)+1;
        int right = maxDepth(root->right)+1;

        return left > right ? left : right;
    }
};

105Construct Binary Tree from Preorder and Inorder Traversal---二叉树的重建


题目解析:

1. 根据二叉树遍历的前序和中序序列来重建二叉树。

2. 如果是根据二叉树前序、中序或者中序、后序都可以重建处二叉树。但是根据二叉树的前序和后序就不能重建一个完整的二叉树。
3.对于此题流程是,前序第一个节点肯定是二叉树的根节点,然后,在中序中找出这个节点,中序序列中,这个节点之前的都是二叉树的左子树,之后的都是二叉树的右子树。然后在左子树和右子树中继续进行上述递归操作。


代码如下:

class Solution {
public:
    // 根据前序和中序遍历结果,构造二叉树
    TreeNode* ConstructCore(vector<int>& preorder, vector<int>& inorder, int prel, int prer, int inl, int inr)
    {
        if(prel>prer || inl>inr)
            return NULL;
        // 前序遍历的第一个节点是根节点的值
        TreeNode *root = new TreeNode(preorder[prel]); 
        if(prel == prer)
            return root;
        // 在中序遍历中找到根节点的值
        int i=inl;
        while(i<=inr && inorder[i] != root->val)
            ++i;
        if(i>inr)
            return NULL;
        int leftlength = i-inl;
        if(leftlength>0)
        {
            // 构建左子树
            root->left = ConstructCore(preorder, inorder, prel+1, prel+leftlength, inl, i-1);
        }
        if(i < inr)
        {
            // 构建右子树
            root->right = ConstructCore(preorder, inorder, prel+leftlength+1, prer, i+1, inr);
        }
        
        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) 
    {
        if(preorder.empty() || preorder.size() != inorder.size())
            return NULL;
        
        int size = (int)preorder.size();
        return ConstructCore(preorder, inorder, 0, size-1, 0, size-1);
    }
};

108Convert Sorted Array to Binary Search Tree---将排序数组转化为二叉平衡搜索树

题目描述:

Given an array where elements are sorted in ascending order, convert it to a height balanced BST.

For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.


Example:

Given the sorted array: [-10,-3,0,5,9],

One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST:

      0
     / \
   -3   9
   /   /
 -10  5

题目解析:

1. 题目要求是给定一个排序数组,将其转化为一个二叉平衡搜索树。
2. 可以想到用二分查找的办法来做,以保证当前节点的左右子树平衡性。每次去中间结点为根,那么这个节点左边的都是其左子树,右边的都是其右子树。


代码如下:
class Solution {
public:
    // 生成一个二叉平衡树
    TreeNode* ConvertCore(vector<int>& nums, int l, int r)
    {
        if(l > r)
            return NULL;
        int mid = (l+r)/2;
        TreeNode *root = new TreeNode(nums[mid]);
        if(l == r)
            return root;
        if(mid > l)
            root->left = ConvertCore(nums, l, mid-1);
        if(mid<r)
            root->right = ConvertCore(nums, mid+1, r);
        
        return root;
    }
    TreeNode* sortedArrayToBST(vector<int>& nums) 
    {
        if(nums.empty())
            return NULL;
        int size = (int)nums.size();
        return ConvertCore(nums, 0, size-1);
    }
};

109Convert Sorted List to Binary Search Tree---将排序队列转化为平衡搜索树

问题描述:

Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.

For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.


Example:

Given the sorted linked list: [-10,-3,0,5,9],

One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST:

      0
     / \
   -3   9
   /   /
 -10  5

问题解析:

1. 此题要求和上题一样,都是将排序的一堆数转为二叉平衡搜索树。但是,这次给的不是数组,而是排序的队列。这个时候就不能直接用二分搜索了。结合中序遍历的二分搜索可以直接解决问题。


代码如下:

class Solution {
public:
    TreeNode *sortedListToBST(ListNode *head)  
   {  
    int len = 0;  
       ListNode * node = head;  
       while (node != NULL)  
       {  
           node = node->next;  
           len++;  
       }  
       return buildTree(head, 0, len-1);  
   }  
     
   TreeNode *buildTree(ListNode *&node, int start, int end)  
   {  
       if (start > end) return NULL;  
       int mid = start + (end - start)/2;  
       TreeNode *left = buildTree(node, start, mid-1);  
       TreeNode *root = new TreeNode(node->val);  
       root->left = left;  
       node = node->next;  
       root->right = buildTree(node, mid+1, end);  
       return root;
   }
};
103 Binary Tree Zigzag Level Order Traversal
104 Maximum Depth of Binary Tree
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
创建一个有n个结点的完全二叉树的过程如下: 1. 如果n为0,则返回空树。 2. 如果n为1,则创建一个只有根节点的树。 3. 如果n为奇数,则将n减1,使之为偶数。 4. 将n除以2,并将商保存为m。 5. 创建一个根节点。 6. 递归创建一个有m个结点的完全二叉树,并将其作为根节点的左子树。 7. 递归创建一个有m个结点的完全二叉树,并将其作为根节点的右子树。 8. 返回根节点。 判断一个二叉树是否为完全二叉树的方法如下: 1. 对于一个二叉树的每个节点,如果它有右子树但是没有左子树,则该二叉树不是完全二叉树。 2. 对于一个二叉树的每个节点,如果它有左子树但是没有右子树,则该二叉树只有当该节点所在的层次为最后一层或者倒数第二层时才是完全二叉树。 3. 对于一个二叉树的每个节点,如果它既有左子树又有右子树,则该二叉树只有当该节点的左子树和右子树都是完全二叉树时才是完全二叉树。 创建一个有n个结点的非完全二叉树,并判断其是否为完全二叉树的方法如下: 1. 首先创建一个有n个结点的二叉树。 2. 找到该二叉树中最大的编号k,使得编号1到k的节点都存在。 3. 对于编号k+1到n的节点,如果它们存在,则该二叉树不是完全二叉树。 4. 如果该二叉树中所有节点都存在,则按照完全二叉树的方法进行判断即可。 注意:在这里,节点的编号指的是按照完全二叉树的方式给每个节点编号,根节点的编号为1,左子节点的编号为2k,右子节点的编号为2k+1。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值