[LeetCode] 101. Symmetric Binary Tree

Problem Description

Given a binary tree, check that it is mirrored symmetrical.

For example, a binary tree [1,2,2,3,4,4,3] is symmetric.

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

Advanced:

Can you solve this problem recursively and iteratively?

Source: LeetCode
Links: https://leetcode-cn.com/problems/symmetric-tree
Copyright shall be owned by the withholding network. For commercial reprinting, please contact the official authorization. For non-commercial reprinting, please indicate the source.

Method I: Recursive implementation

Code:

//Symmetric Binary Tree--Recursive Implementation
class Solution {
public:
	bool isSymmetric(TreeNode* root) {
		if (root != nullptr) {
			return helper(root->left, root->right);
		}
		else {
			return true;
		}
	}

	bool helper(TreeNode* leftTree, TreeNode* rightTree) {
		if (leftTree == nullptr && rightTree == nullptr) {
			return true;
		}
		else if (leftTree != nullptr && rightTree != nullptr) {
			if (leftTree->val != rightTree->val) {
				return false;
			}
			return helper(leftTree->left, rightTree->right) && helper(leftTree->right, rightTree->left);
		}
		else {//Two trees, only one is Null
			return false;
		}
	}
};

Execution results:

Write about the code idea:

The recursive function helper implements whether two trees are mirrored or not.

If the boundary condition is that both trees are empty, then return true.

For some special cases, we can consider them separately to improve efficiency: 1. If only one tree is empty, then false is returned; 2. Returns false if neither tree is empty but the root node values are not equal.

Recursive scenarios remain: we consider the mirroring of the subtrees of the two trees: 1. Whether the left child of leftTree and the right child of rightTree are mirrored; 2. Whether the right child of leftTree is mirrored with the left child of rightTree. Then return the Boolean value that matches it.

Fa II: Recursion (official puzzle)

Actually, I think the same way, but the official code is more concise.

class Solution {
public:
    bool check(TreeNode *p, TreeNode *q) {
        if (!p && !q) return true;
        if (!p || !q) return false;
        return p->val == q->val && check(p->left, q->right) && check(p->right, q->left);
    }

    bool isSymmetric(TreeNode* root) {
        return check(root, root);
    }
};

Method III: Iterative implementation (using median traversal: left middle right/right middle left)

//Iterative implementation - traversal through middle order
class Solution {
public:
	bool isSymmetric(TreeNode* root) {
		if (root == nullptr) {
			return true;
		}
		TreeNode* currentLeft = root->left;
		TreeNode* currentRight = root->right;
		stack<TreeNode*> stLeft;
		stack<TreeNode*> stRight;
		while ((currentLeft != nullptr || !stLeft.empty()) && (currentRight != nullptr || !stRight.empty())) {
			while (currentLeft != nullptr && currentRight != nullptr) {
				stLeft.push(currentLeft);
				currentLeft = currentLeft->left;
				stRight.push(currentRight);
				currentRight = currentRight->right;
			}
			if (currentLeft == nullptr && currentRight == nullptr) {
				currentLeft = stLeft.top();
				stLeft.pop();
				currentRight = stRight.top();
				stRight.pop();
				if (currentLeft->val != currentRight->val) {
					return false;
				}
				currentLeft = currentLeft->right;
				currentRight = currentRight->left;
			}
			else {
				return false;
			}
		}
		if (!(currentLeft != nullptr || !stLeft.empty()) && !(currentRight != nullptr || !stRight.empty())) {
			return true;
		}
		else {
			return false;
		}
	}
};


Analysis: If the left subtree completes the middle-order traversal through the left middle-right and the right subtree completes the middle-order traversal through the right middle-left, the values corresponding to the output (out of stack) should be the same. Otherwise the description is not a mirror.

Fa IV: Iteration (official puzzle)

In Method One, we use a recursive method to judge symmetry, so how do we use an iterative method? First, we introduce a queue, which is a common way to rewrite a recursive program into an iterator. We queue the root node twice at initialization. Extract two nodes at a time and compare their values (each two consecutive nodes in the queue should be equal and their subtrees mirror each other), then insert the left and right child nodes of the two nodes into the queue in reverse order. The algorithm ends when the queue is empty or when we detect tree asymmetry, which is when two unequal continuous nodes are removed from the queue.

class Solution {
public:
    bool check(TreeNode *u, TreeNode *v) {
        queue <TreeNode*> q;
        q.push(u); q.push(v);
        while (!q.empty()) {
            u = q.front(); q.pop();
            v = q.front(); q.pop();
            if (!u && !v) continue;
            if ((!u || !v) || (u->val != v->val)) return false;

            q.push(u->left); 
            q.push(v->right);

            q.push(u->right); 
            q.push(v->left);
        }
        return true;
    }

    bool isSymmetric(TreeNode* root) {
        return check(root, root);
    }
};

Note the queue FIFO.

Tags: Algorithm leetcode

Posted on Thu, 21 Oct 2021 14:39:36 -0400 by crseader