OJ topic 2 -- recursion in nested form

Posted by rledieu on Tue, 01 Feb 2022 15:12:18 +0100

The so-called nested form of recursion, according to my understanding, is that the form of recursion is relatively complex, which can not be made clear in a simple sentence. This requires two layers of recursion for nesting to achieve the purpose. For example, to calculate the number of nodes in a binary tree, the fundamental logic to solve this problem is that the number of nodes in a binary tree is equal to the root node itself plus the number of nodes in the left subtree of the root node and the number of nodes in the right subtree of the root node. And so on until it reaches the root node (the criterion is that after the recursion with the leaf node as the root node is calculated, the left and right child nodes must be empty, so the node is empty, which becomes the end condition). Of course, the simple logic of the above problem can be realized through one-time recursion. However, the logic of many recursive problems is not always so simple. The solution of the whole problem can not be realized by repeated execution in one sentence, which requires nested recursion. For example, to judge whether a binary tree is a symmetric binary tree, when starting from the root node, of course, it is necessary to compare whether the left and right child nodes are the same, but after this comparison, the following comparison cannot be realized by comparing the left and right children, because this is when comparing whether the left and right children are the same, The whole program will appear nondescript (of course, this method is correct when comparing whether the binary tree is a single valued binary tree). The situation at this time is that the calculation cannot be completed repeatedly in a simple sentence, which requires nested recursion.

1. Judge whether a binary tree is a symmetric binary tree.

101. Symmetric binary tree LeetCode (LeetCode CN. Com)

Through two layers of recursive nesting, we can compare the left child node of the right child node with the right child node of the left child node. By analogy, the left child node of the left child node of the right child node is compared with the right child node of the right child node of the left child node. No matter how the two nodes are compared, the "left" and "right" of judging the identity of the node are always opposite, which can ensure the symmetry axis symmetry of the two nodes compared with respect to the binary tree. Of course, the end condition of nested recursion is the same as that of ordinary recursion. It will end only when it reaches the end of the binary tree or finds that the values of two nodes at symmetrical positions are not equal, otherwise it will continue to be calculated.

bool ist(struct TreeNode*root1,struct TreeNode*root2)
{
    if(root1==NULL&&root2==NULL)
    {
        return true;
    }
    if(root1==NULL||root2==NULL)
    {
        return false;
    }
    if(root1->val!=root2->val)
    {
        return false;
    }
    return ist(root1->left,root2->right)&&ist(root1->right,root2->left);
}
bool isSymmetric(struct TreeNode* root)
{
    if(root==NULL)
    {
        return true;
    }
    return ist(root->left,root->right);
}

2. Judge whether a tree is a subtree of another tree.

572. LeetCode, a subtree of another tree (LeetCode CN. Com)

To judge whether a tree is a subtree of another tree, you need to take out each node in the larger tree and compare it with the small tree. If it does not meet the requirements, take out the left and right child nodes of the node and compare them with the small tree respectively. However, the tree to be compared is not a simple node. If it is a simple node, it is no different from finding a node with a value of x in a binary tree. Therefore, the logic of this problem is still more complex than the logic of recursive call repeatedly implemented in one sentence, so nested recursion is needed. The extra recursion is mainly used to compare whether two binary trees are equal (in this step, one equal sign can be used to find the node with the value of x in the binary tree, but comparing two binary trees cannot be solved by one equal sign, which is the core of nested recursion to solve this problem)

bool isSameTree(struct TreeNode*q1,struct TreeNode*q2)
{
    if(q1==NULL&&q2==NULL) //When both nodes are empty, since q1 and q2 here are essentially derived from the following recursion, q1 and q2 are actually the left and right child nodes of a node. When the left and right child nodes of a node are empty, it indicates that the node is already a leaf node. When the leaf node is compared, it indicates that the two trees are the same
    {
        return true;
    }
    if(q1==NULL||q2==NULL) //The first and second of the classical if structures are recursive
    {
        return false;
    }
    if(q1->val==q2->val)
    {
        return isSameTree(q1->left,q2->left)&&isSameTree(q1->right,q2->right); //This recursive function is essentially to compare whether two nodes are the same, but combined to achieve the effect of comparing whether two trees are the same
    }
    else
    {
        return false;
    }
}
bool isSubtree(struct TreeNode* s, struct TreeNode* t) 
{
    if(s==NULL) //When the s node is empty, it means that no qualified subtree can be found even at the end of the tree, so false should be returned
    {
        return false;
    }
    if(isSameTree(s,t)) //When the two trees with s node and t node as the root node are the same, it means that I have found a qualified subtree
    {
        return true;
    }
    Else//If you can't determine success or failure, you should continue to compare downward. Pay attention to the logic of or here, because as long as there is a tree with a node as the root node equal to the tree to be compared, you can draw a conclusion. Therefore, you should use or logic
    {
        return isSubtree(s->right,t)||isSubtree(s->left,t);
    }
}

In contrast, we can compare the above code for finding the node with the value of x in the binary tree:

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
		return NULL;
	if (root->data == x)
		return root;
	BTNode* leftRet = BinaryTreeFind(root->left, x);
	if (leftRet)
		return leftRet;
	BTNode* rightRet = BinaryTreeFind(root->right, x);
	if (rightRet)
		return rightRet;
	return NULL;
}

Topics: Algorithm data structure