Collection of binary tree questions (C++)

1. Binary tree creates string (simple)

Link:Binary tree creates string

Topic requirements:
Insert image description here

PS: The description of the question is not very clear. In fact, it is preorder traversal of tree, and then < /span>. Enclose the left subtree and right subtree traversal results in parentheses

Basic idea:
(1) If bracket deduplication is not considered , in fact, as long as has finished accessing the current Just recursively access the left and right subtrees after the node, and add a left bracket before the access, and a right bracket after the access is completed. When the current node is empty, return < /span> is enough. The code is as follows:

class Solution {
    
    
public:
    string ret;
    string tree2str(TreeNode* root) {
    
    
        dfs(root);
        return ret;
    }

    void dfs(TreeNode* root)
    {
    
    
        if(root == nullptr)  return;
        ret += to_string(root->val);
        ret += '(', dfs(root->left), ret += ')';
        ret += '(', dfs(root->right), ret += ')';
    }
};

Insert image description here


(2) For bracket deduplication, mainly around the left and right subtrees are empty, we need Discuss on a case-by-case basis:
Insert image description here


Code:

class Solution {
    
    
public:
    string ret;
    string tree2str(TreeNode* root) {
    
    
        dfs(root);
        return ret;
    }

    void dfs(TreeNode* root)
    {
    
    
        if(root == nullptr)  return;
        ret += to_string(root->val);
        if(root->left || root->right)  ret += '(', dfs(root->left), ret += ')';
        if(root->right)  ret += '(', dfs(root->right), ret += ')';
    }
};



2. Hierarchical traversal of binary trees (medium)

Link:Hierarchical traversal of binary tree

Topic requirements:
Insert image description here


Basic idea:
(1) The idea of ​​binary tree level order traversal is actually very simple, that is, with the help of queues, The parent node brings out the child node, and relies on the first-in-first-out feature of the queue to control the access sequence.
Insert image description here

(2) The key point of this question isHow to know the number of nodes in the current layer and the next layer, because we need to build an array for each layer to store the results. The solution adopted here is to use a next variable to record the number of nodes in the next layer, and count (count is initially 1) to record the number of nodes in the current layer. After accessing the current layer, assign next to count.


Code:

class Solution {
    
    
public:
    vector<vector<int>> ret;
    vector<vector<int>> levelOrder(TreeNode* root) {
    
    
        if(root == nullptr)  return ret;
        queue<TreeNode*> q;
        q.push(root);
        int count = 1;  //每一层的节点数
        while(!q.empty())
        {
    
    
            vector<int> tmp;
            int next = 0;  //用一个变量记录下一层的节点
            for(int i = 0; i < count; i++)
            {
    
    
                TreeNode* node = q.front();
                q.pop();
                tmp.push_back(node->val);      
                if(node->left)  q.push(node->left), next++;   
                if(node->right)  q.push(node->right), next++;           
            }
            count = next;
            ret.push_back(tmp);
        }
        return ret;
    }
};



3. The most recent common ancestor of a binary tree (medium)

Link:The nearest common ancestor of a binary tree
Question requirements:
Insert image description here

  1. Solution 1 (high time complexity):
    Basic idea:
    Insert image description here

Solution one code:

//理想是N*logN,对于退化成链表的情况变成O(N ^ N)
class Solution {
    
    
public:
    bool isTree(TreeNode* root, TreeNode* x)
    {
    
    
        if(root == nullptr)  return false;
        if(root->val == x->val)  return true;
        return isTree(root->left, x) || isTree(root->right, x);
    }

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    
    
        if(root == p || root == q)  return root;
        bool pInLeft = isTree(root->left, p);
        bool pInRight = !pInLeft;  //不在左树就在右树
        bool qInLeft = isTree(root->left, q);
        bool qInRight = !qInLeft;
        if((pInLeft && qInRight) || (pInRight && qInLeft))  //p,q分别在左右子树
            return root;
        if(pInLeft && qInLeft)  return lowestCommonAncestor(root->left, p, q); //pq都在左树
        else  return lowestCommonAncestor(root->right, p, q);  //pq都在右树
    }
};

  1. Solution 2 (low time complexity):
    Basic idea:
    The second idea is not difficult, Find the path from the root to the p and q nodes, Find the intersecting nodes from back to front That’s it, it’s hard to understand, so just look at the picture:
    Insert image description here

Solution two code:

//找路径,转换为链表交点,用栈来存储路径,O(N)
class Solution {
    
    
public:
    bool FindPath(TreeNode* root, TreeNode* x, stack<TreeNode*>& path)
    {
    
    
        if(root == nullptr)  return false;
        path.push(root); //不管怎么说,先入栈
        if(root == x)  return true;
        if(FindPath(root->left, x, path))  return true;  //递归走左找到了,直接返回
        if(FindPath(root->right, x, path))  return true;  //递归走右找到了,直接返回
        //左右子树都没有,当前这个节点出栈
        path.pop(); 
        return false;
    }

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 
    {
    
    
        stack<TreeNode*> path1;
        stack<TreeNode*> path2;
        FindPath(root, p, path1);
        FindPath(root, q, path2);
        while(path1.size() != path2.size())  //长路径先走
        {
    
    
            if(path1.size() > path2.size())  path1.pop();
            else  path2.pop();
        }
        while(path1.top() != path2.top())
        {
    
    
            path1.pop(), path2.pop();
        }
        return path1.top();  //随便返回一个即可
    }
};



4. Convert the binary search tree into a sorted doubly linked list (medium)

Link:Binary tree search tree converted into sorted doubly linked list

Topic requirements:
Insert image description here

Basic idea:
(1) Because it is a search tree, we use something like in-order traversal way to solve the problem.
(2) The key to this question is to find the preceding node . As long as you find the preceding node of the current node, you can proceed. Link.

The specific process is as follows:

  1. Two pointers, prev records the previous one, cur records the current one,prev is initially empty
  2. cur is empty, return.
  3. (1) cur is not empty, recursively go to the left first;
    (2) After finishing the left move, prev is the front, link: cur->left = prev, prev- >right = cur (here prev is not empty).
    (3)Update the prefix after the link is completed, prev = cur.
    (4) After walking left, recurse right and link the right subtree.
  4. Finally, you need to determine the head node of the linked list. This can be done
    ① before conversion: find the node in the lower left corner of the tree. ②After conversion, find: from the original root node to the left .

First recurse all the way to the left until you reach the empty space:
Insert image description here

Code:

class Solution {
    
    
public:
	void _Convert_order(TreeNode* cur, TreeNode*& prev)
	{
    
    
		if(cur == nullptr)  return;
		_Convert_order(cur->left, prev);
		cur->left = prev;
		if(prev)  prev->right = cur;
		prev = cur;
		_Convert_order(cur->right, prev);
	}
	
    TreeNode* Convert(TreeNode* pRootOfTree) 
	{
    
    
        TreeNode* cur = pRootOfTree, *prev = nullptr;
		_Convert_order(cur, prev);
		TreeNode* ret = pRootOfTree;
		while(ret && ret->left)  //(1)有空树的情况(2)先链接好再向左找目标节点即可
		{
    
    
			ret = ret->left;
		}
		return ret;
    }
};



5. Construct a binary tree based on pre-order traversal and in-order traversal of the tree (medium)

Link:Construct a binary tree

Topic requirements:
Insert image description here

Basic idea:
(1)The front order determines the root, and the middle order determines the left and right sides.
(2) First construct the root , then find the position of the current node in the in-order array, and put the left and right subtrees Nodes are divided.
(3) Recursively go to the left and right according to the divided mid-order interval. The absence of the interval means that this position is empty. , returns empty.
Just link them after walking left and right. The left and right links are completedReturn the root node of the tree.

Processing details:
(1) How to find the position of the current node in the in-order array:
①One way is to traverse the in-order interval, In this way, each layer needs to be traversed, and the time complexity is high
②One is touse a hash table for storage, Using values ​​to map in-order subscripts has low time complexity.
This article selects method ②.

Follow the process ofpreorder traversal:
Insert image description here


Code:

class Solution {
    
    
public:
    unordered_map<int, int> ord;
    TreeNode* _buildTree(vector<int>& preorder, vector<int>& inorder, int& prei, int inbegin, int inend)
    {
    
    
        if(inbegin > inend)  return nullptr;  //区间不存在返回空
        TreeNode* root = new TreeNode(preorder[prei]);
        int rooti = ord[preorder[prei++]];
        //划分出三段区间:[inbegin, rooti - 1] rooti [rooti + 1, inend]
        root->left = _buildTree(preorder, inorder, prei, inbegin, rooti - 1);
        root->right = _buildTree(preorder, inorder, prei, rooti + 1, inend);
        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
    
    
        for(int i = 0; i < inorder.size(); i++)
        {
    
    
            ord[inorder[i]] = i;
        }
        int i = 0;
        return _buildTree(preorder, inorder, i, 0, inorder.size() - 1);
    }
};

Guess you like

Origin blog.csdn.net/2301_76269963/article/details/134103649