notes/OJ notes/pages/Leetcode Symmetric-Tree.md
2022-07-08 11:29:47 +08:00

4.5 KiB

Leetcode Symmetric-Tree

2022-07-05 10:15

Algorithms:

#algorithm #DFS #recursion #BFS

Data structures:

#DS #binary_tree

Difficulty:

#coding_problem #difficulty-easy

Additional tags:

#leetcode

Revisions:

N/A

tag:#DFS OR tag:#BFS

Problem

Given the root of a binary tree, check whether it is a mirror of itself (i.e., symmetric around its center).

Examples

Example 1:

Input: root = [1,2,2,3,4,4,3] Output: true

Example 2:

Input: root = [1,2,2,null,3,null,3] Output: false

Constraints

Constraints:

  • The number of nodes in the tree is in the range [1, 1000].
  • -100 <= Node.val <= 100

Thoughts

[!summary] This is a #DFS #recursion problem

Method 1, DFS-like Recursion:

  • Base Cases:
    • left and right are nullptr: true
    • else if left or right is nullptr: false, must be asymmetric
    • left->val != right->val: false
  • return check(left->left, right->right) && check(left->right, right->left)

Method 2, BFS-like Iteration: In the while loop:

  • Take two nodes from queue, they should be matched.
  • if both are nullptr, continue.
  • if one is nullptr, return false.
  • if val doesn't match, return false.
  • add left->left and right->right to queue (they will be matched as a pair)
  • add left->right and right->left to queue (they will be matched as a pair)

Solution

Recursion, 16ms

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left),
 * right(right) {}
 * };
 */
class Solution {
  bool checkSymmetric(TreeNode *left, TreeNode *right) {
    // If only one child is leaf it is not symmetric
    if (!left && !right) {
      return true;
    } else if (!left || !right) {
      return false;
    }

    if (left->val != right->val) {
      return false;
    }

    // One node has two childs, traverse them in pairs.
    return checkSymmetric(left->right, right->left) &&
           checkSymmetric(left->left, right->right);
  }

public:
  bool isSymmetric(TreeNode *root) {
    // DFS-like recursion
    return checkSymmetric(root->left, root->right);
  }
};

BFS, iteration, 8ms

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left),
 * right(right) {}
 * };
 */
class Solution {
  bool checkLeaves(TreeNode *l, TreeNode *r) {
    // Check if the leaves are symmetric.
    if (!l && !r) {
      return true;
    } else if (!l || !r) {
      return false;
    }
    return true;
  }

public:
  bool isSymmetric(TreeNode *root) {
    // BFS-like iteration, using queue.

    // Ensure root has two childs
    if (!checkLeaves(root->left, root->right)) {
      return false;
    }

    queue<TreeNode *> pending;
    pending.push(root->left);
    pending.push(root->right);

    TreeNode *l, *r;

    while (!pending.empty()) {
      l = pending.front();
      pending.pop();
      r = pending.front();
      pending.pop();

      if (l && r) {
        // Check val of l and r
        if (l->val != r->val) {
          return false;
        }
        // Chech if the child nodes are symmetric
        if (!(checkLeaves(l->left, r->right) &&
              checkLeaves(l->right, r->left))) {
          return false;
        }

        // Add more to queue
        pending.push(l->left);
        pending.push(r->right);
        pending.push(l->right);
        pending.push(r->left);
      }
    }

    return true;
  }
};