《剑指Offer》二叉树系列15道算法面试题解析(C++)

版权声明:本文为博主整理文章,未经博主允许不得转载。 https://blog.csdn.net/ZYZMZM_/article/details/90762055


1、重建二叉树

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

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        int preSize = pre.size();
        int vinSize = vin.size();
        if(preSize <= 0 || vinSize <= 0)
            return nullptr;
        return reConstructBinaryTree(pre, vin, 0, preSize - 1, 0, vinSize - 1);
    }
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin,int i, int j, int m, int n)
    {
        if(i > j || m > n)
            return nullptr;
        
        TreeNode *node = new TreeNode(pre[i]);
        for(int k = m; k <= n; ++k)
        {
            if (pre[i] == vin[k])
            {
                node->left = reConstructBinaryTree(pre, vin, i + 1, i + (k-m), m, k - 1);
                node->right = reConstructBinaryTree(pre, vin, i + (k-m) + 1, j, k + 1, n);
                break;
            }
        }
        return node;
    }
};

2、树的子结构

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

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
    {
        bool result = false;
        if(pRoot1 != nullptr && pRoot2 != nullptr)
        {
            if(pRoot1->val == pRoot2->val)
                result = isSubtree(pRoot1, pRoot2);
                
            if(!result)
                result = HasSubtree(pRoot1->left, pRoot2);
            
            if(!result)
                result =HasSubtree(pRoot1->right, pRoot2);
        }
        return result;
    }
    
    bool isSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
    {
        if(pRoot2 == nullptr)
            return true;
        
        if(pRoot1 == nullptr)
            return false;

        if(pRoot1->val != pRoot2->val)
            return false;

        return isSubtree(pRoot1->left, pRoot2->left)
            && isSubtree(pRoot1->right, pRoot2->right);
    }
};

3、二叉树的镜像

题目描述:操作给定的二叉树,将其变换为源二叉树的镜像。

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    void Mirror(TreeNode *pRoot) {
        if(pRoot == nullptr)
            return;
        
        TreeNode *tmpNode = pRoot->left;
        pRoot->left = pRoot->right;
        pRoot->right = tmpNode;
        
        Mirror(pRoot->left);
        Mirror(pRoot->right);
    }
};

4、从上往下打印二叉树

题目描述:从上往下打印出二叉树的每个节点,同层节点从左至右打印。

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/

/* 非递归 */
class Solution {
public:
    vector<int> PrintFromTopToBottom(TreeNode* root) {
        
        vector<int> result;
        queue<TreeNode*> queue;
        if(root != nullptr)
        {
            queue.push(root);
            while(queue.size())
            {
                TreeNode* node = queue.front();
                queue.pop();
                result.push_back(node->val);
                if(node->left != nullptr)
                    queue.push(node->left);
                if(node->right != nullptr)
                    queue.push(node->right);
            }
        }
        return result;
    }
};

/* 递归 */
/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    int level(TreeNode* root)
    {
        if(root == nullptr)
            return 0;
        
        int left = level(root->left);
        int right = level(root->right);
        return (left > right ? left : right) + 1;
    }
    
    vector<int> PrintFromTopToBottom(TreeNode* root) {
        vector<int> result;

        int levelNum = level(root);
        for(int i = 0; i < levelNum; ++i)
        {
            PrintFromTopToBottom2(root, i, result);
        }

        return result;
        
    }
    
    
    void PrintFromTopToBottom2(TreeNode* root, int n, vector<int> &result) {
        
       if(root == nullptr)
           return;
        
       if (n == 0)
       {
           result.push_back(root->val);
       }
       else
       {
           PrintFromTopToBottom2(root->left, n - 1, result);
           PrintFromTopToBottom2(root->right, n - 1, result);
       }
    }
};

5、二叉搜索树的后序遍历序列

题目描述:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。
假设输入的数组的任意两个数字都互不相同。

class Solution {
public:
    bool VerifySquenceOfBST(vector<int> sequence) {
        return VerifySquenceOfBST(sequence, 0, sequence.size() - 1);
    }
    
    bool VerifySquenceOfBST(vector<int> sequence, int begin, int end) {
        if(sequence.empty() || begin > end)
            return false;
        
        int root = sequence[end];
        int i = begin;
        for(; i < end; ++i)
        {
            if(sequence[i] > root)
            {
                break;
            }
        }
        
        for(int j = i; j < end; ++j)
        {
            if(sequence[j] < root)
            {
                return false;
            }
        }
        
        bool left = true;
        if(i > begin)
            left = VerifySquenceOfBST(sequence, begin, i - 1);
        
        bool right = true;
        if(i < end - 1)
            right = VerifySquenceOfBST(sequence, begin + i, end - 1);
        
        return left && right;
    }
};

6、二叉树中和为某一值的路径

题目描述:输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意:
在返回值的list中,数组长度大的数组靠前)

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
        vector<vector<int> > result;
        vector<int> tmp;
        
        return FindPath(root, expectNumber, tmp, result);
    }
    vector<vector<int> > FindPath(TreeNode* root,int expectNumber,vector<int> &tmp, vector<vector<int> > &result){
        if(root == nullptr)
            return result;
        
        tmp.push_back(root->val);
        if(expectNumber == root->val && root->left == nullptr && root->right == nullptr)
        {
            result.push_back(tmp);
        }
        
        expectNumber -= root->val;
        if(root->left != nullptr)
            FindPath(root->left, expectNumber, tmp, result);
        if(root->right != nullptr)
            FindPath(root->right, expectNumber, tmp, result);
        
        if(!tmp.empty())
            tmp.pop_back();
        
        return result;
    }
};

7、二叉搜索树与双向链表

题目描述:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

 /*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    TreeNode* Convert(TreeNode* pRootOfTree)
    {
        if(pRootOfTree == nullptr)
            return nullptr;
        
        TreeNode* node = nullptr;
        Convert(pRootOfTree, node);
        
        while(node != nullptr && node->left != nullptr)
        {
            node = node->left;
        }
        
        return node;
    }
    void Convert(TreeNode* pRootOfTree, TreeNode* &lastNodeInList)
    {
        if(pRootOfTree == nullptr)
            return;
        
        TreeNode* curNode= pRootOfTree;
        if(curNode->left != nullptr)
            Convert(curNode->left, lastNodeInList);
        
        curNode->left = lastNodeInList;
        if(lastNodeInList != nullptr)
            lastNodeInList->right = curNode;
        
        lastNodeInList = curNode;
        
        if(curNode->right != nullptr)
            Convert(curNode->right, lastNodeInList);
    }
};

8、二叉树的深度

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

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    int TreeDepth(TreeNode* pRoot)
    {
        if(pRoot == nullptr)
            return 0;
        
        int leftDepth = TreeDepth(pRoot->left);
        int rightDepth = TreeDepth(pRoot->right);
        
        return (leftDepth > rightDepth ? leftDepth : rightDepth) + 1;
    }
};

9、平衡二叉树

题目描述:输入一棵二叉树,判断该二叉树是否是平衡二叉树。

class Solution {
public:
    
    bool IsBalanced_Solution(TreeNode* pRoot) {
        if(pRoot == nullptr)
            return true;
        
        if(abs(TreeDepth(pRoot->left) - TreeDepth(pRoot->right)) > 1)
            return false;
        
        return IsBalanced_Solution(pRoot->left)
            && IsBalanced_Solution(pRoot->right);
    }
    
    int TreeDepth(TreeNode* pRoot)
    {
        if(pRoot == nullptr)
            return 0;
        
        int leftDepth = TreeDepth(pRoot->left);
        int rightDepth = TreeDepth(pRoot->right);
        
        return (leftDepth > rightDepth ? leftDepth : rightDepth) + 1;
    }
};

10、二叉树的下一个结点

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

/*
struct TreeLinkNode {
    int val;
    struct TreeLinkNode *left;
    struct TreeLinkNode *right;
    struct TreeLinkNode *next;
    TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
        
    }
};
*/
class Solution {
public:
    TreeLinkNode* GetNext(TreeLinkNode* pNode)
    {
        if(pNode == nullptr)
            return nullptr;
        
        TreeLinkNode *result  = nullptr;
        
        if(pNode->right != nullptr)
        {
            TreeLinkNode *node = pNode->right;
            while(node->left != nullptr)
            {
                node = node->left;
            }
            result = node;
        }
        else if (pNode->next != nullptr)
        {
            TreeLinkNode* curNode = pNode;
            TreeLinkNode* parent = pNode->next;
            while(parent != nullptr && curNode != parent->left)
            {
                curNode = parent;
                parent = parent->next;
            }
            result = parent;
        }
        return result;
    }
};

11、对称的二叉树

题目描述 : 请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    bool isSymmetrical(TreeNode* pRoot)
    {
        return isSymmetrical(pRoot, pRoot);
    }
    bool isSymmetrical(TreeNode* pRoot1, TreeNode* pRoot2)
    {
        if(pRoot1 == nullptr && pRoot2 == nullptr)
            return true;
       
        if(pRoot1 == nullptr || pRoot2 == nullptr)
            return false;
        
        if(pRoot1->val != pRoot2->val)
            return false;
        
        return isSymmetrical(pRoot1->left, pRoot2->right)
            && isSymmetrical(pRoot1->right, pRoot2->left);
    }
};

12、按之字形顺序打印二叉树

题目描述 :请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    vector<vector<int> > Print(TreeNode* pRoot) {
        vector<vector<int> > result;
        if(pRoot == nullptr)
            return result;
        
        stack<TreeNode *> stack1;
        stack<TreeNode *> stack2;

        stack1.push(pRoot);
        while(!stack1.empty() || !stack2.empty())
        {
            if(!stack1.empty())
            {
                vector<int> tmp;
                while(!stack1.empty())
                {
                    TreeNode *top = stack1.top();
                    stack1.pop();
                    tmp.push_back(top->val);
                    if(top->left != nullptr)
                        stack2.push(top->left);
                    if(top->right != nullptr)
                        stack2.push(top->right);
                }
                result.push_back(tmp);
            }
            if(!stack2.empty())
            {
                vector<int> tmp;
                while(!stack2.empty())
                {
                    TreeNode *top = stack2.top();
                    stack2.pop();
                    tmp.push_back(top->val);
                    if(top->right != nullptr)
                        stack1.push(top->right);
                    if(top->left != nullptr)
                        stack1.push(top->left);
                }
                result.push_back(tmp);
            }
        }
        return result;
    }
};

13、把二叉树打印成多行

题目描述:从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

 /*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
        vector<vector<int> > Print(TreeNode* pRoot) {
            vector<vector<int> > result;
            if(pRoot == nullptr)
                return result;
            
            queue<TreeNode*> queue;
            queue.push(pRoot);

            while (!queue.empty())
            {
                int size = queue.size();
                vector<int> tmp;
                while(size != 0)
                {
                    TreeNode *node = queue.front();
                    tmp.push_back(node->val);
                    queue.pop();
                    if(node->left != nullptr)
                    {
                        queue.push(node->left);
                    }
                    if(node->right != nullptr)
                    {
                        queue.push(node->right);
                    }
                    --size;
                }
                result.push_back(tmp);
            }
            return result;
        }
};

14、序列化二叉树

题目描述 : 请实现两个函数,分别用来序列化和反序列化二叉树

 /*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
/* vector 实现 */
class Solution {
public:
    vector<int> buffer;
    
    void Serialize2(TreeNode *root)
    {
        if(root == nullptr)
        {
            buffer.push_back(0xFFFFFFFF);
            return;
        }
            
        buffer.push_back(root->val);
        Serialize2(root->left);
        Serialize2(root->right);
    }
    
    char* Serialize(TreeNode *root) {
        buffer.clear();
        Serialize2(root);
        int size = buffer.size();
        int* result = new int[size];
        for (int i = 0; i < size; ++i)
        {
            result[i] = buffer[i];
        }
        return (char *)result;
    }
    
    TreeNode* Deserialize2(int * &arr) {
        if(*arr == 0xFFFFFFFF)
        {
            arr++;
            return nullptr;
        }
        
        TreeNode* root = new TreeNode(*arr);
        arr++;
        root->left = Deserialize2(arr);
        root->right = Deserialize2(arr);
        return root;
    }
    
    TreeNode* Deserialize(char *str) {
        int *arr = (int *)str;
        return Deserialize2(arr);
    }
};

/* String 实现 */
class Solution {
public:
    void Serialize2(TreeNode *root, string &str)
    {
        if(root == nullptr)
        {
            str.push_back('#'),
            str.push_back(',');
            return;
        }
        
        str += to_string(root->val);
        str.push_back(',');
        Serialize2(root->left, str);
        Serialize2(root->right, str);
    }
    
    char* Serialize(TreeNode *root) {    
       if(root == nullptr)
           return nullptr;
        string str = "";
        Serialize2(root, str);
        char *result = new char[str.length() + 1];
        strcpy(result, str.c_str());
        return result;
    }
    TreeNode* Deserialize2(string &str) {
        if(str.empty())
            return nullptr;
        if(str[0] == '#')
        {
            str = str.substr(2);
            return nullptr;
        }
        TreeNode* node = new TreeNode(stoi(str));
        str = str.substr(str.find_first_of(',') + 1);
        node->left = Deserialize2(str);
        node->right = Deserialize2(str);
        return node;
    }
    TreeNode* Deserialize(char *s) {
        if(s == nullptr)
            return nullptr;
        string str(s);
        return Deserialize2(str);
    }
};

15、二叉搜索树的第k个结点

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

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
/* version 1 */
class Solution {
public:
    TreeNode* KthNode(TreeNode* pRoot, int k)
    {
        TreeNode* result = nullptr;
        KthNode(pRoot, k, result);
        return result;
    }
    
     void KthNode(TreeNode* pRoot, int &k,  TreeNode* &result)
     {
         if(pRoot != nullptr)
         {
             if(k >= 0)
             {
                 KthNode(pRoot->left, k, result);
                 --k;
                 if(k == 0)
                 {
                     result = pRoot;
                     return;
                 }
                 KthNode(pRoot->right, k, result);
             }
         }
     }
};

/* version 2 */
class Solution {
public:
    TreeNode* KthNode(TreeNode* pRoot, int k)
    {
        int n = 0;
        return KthNode(pRoot, k, n);
    }
    
     TreeNode* KthNode(TreeNode* pRoot, int k, int &n){
         if(pRoot != nullptr)
         {
             TreeNode* p = KthNode(pRoot->left, k, n);
             ++n; 
             if(p != nullptr)
                 return p;
             
             if(k == n)
                 return pRoot;
             
             return KthNode(pRoot->right, k, n);
         }
         return nullptr;
     }
};

猜你喜欢

转载自blog.csdn.net/ZYZMZM_/article/details/90762055