Leetcode P0156"Binary Tree Upside Down" 题解

2020/09/20 Leetcode

博文中会简要介绍Leetcode P0156题目分析及解题思路。

“Binary Tree Upside Down这道题其实很简单,但是这道题的题干描述不是很准确。我个人一开始的思考是认为无论左右子树都需要进行上下翻转的操作,结果最终答案是只有左子树需要这样操作,而右子树保持不变。下面的代码部分同时描述了实际题目的答案和我个人思考的问题的解法。

Given the root of a binary tree, turn the tree upside down and return the new root.

You can turn a binary tree upside down with the following steps:

  • The original left child becomes the new root.
  • The original root becomes the new right child.
  • The original right child becomes the new left child.

The mentioned steps are done level by level, it is guaranteed that every node in the given tree has either 0 or 2 children.

按题目答案来看,无需遍历右子树,首先深度遍历到最左结点找到新的根结点,然后开始对左子树遍历。对于左子树,因为左孩子结点会成为新的根结点,所以下层返回的是本层的左孩子结点,也即下层的原根结点。最后进行Upside Down操作即可。

以下是Java的题解代码实现。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode upsideDownBinaryTree(TreeNode root) {
        if (root == null)
            return root;
        
        // First find the new root
        TreeNode newRoot = root;
        while (newRoot.left != null)
            newRoot = newRoot.left;
        
        this.dfs(root);
        return newRoot;
    }

    private TreeNode dfs(TreeNode curr) {
        if (curr.left == null && curr.right == null)
            return curr;

        TreeNode left = curr.left, right = curr.right;
        if (curr.left != null)
            left = this.dfs(curr.left);
        
        // Upside down
        left.right = curr;
        left.left = right;
        
        curr.left = null;
        curr.right = null;
        
        return curr;
    }
}

以下是我个人思考和认为的Upside Down,即无论左右子树,都需要递归地进行翻转操作,而不是按答案的解法所说右子树无需翻转。在我思考的这种情况下,对于左子树和右子树是两种不同的方法。

对于左子树,因为左孩子结点会成为新的根结点,所以下层返回的是本层的左孩子结点,也即下层的原根结点。

而对于右子树,由于右孩子结点会成为新的左结点,所以下层返回的应当是右子树的新根结点,这样右边子树的新根结点会作为本层的新根结点的左孩子结点。

以下是Java的题解代码实现。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode upsideDownBinaryTree(TreeNode root) {
        if (root == null)
            return root;
        
        return this.dfsRight(root);
    }
    
    
    private TreeNode dfsLeft(TreeNode curr) {
        if (curr.left == null && curr.right == null)
            return curr;
        
        this.upsideDown(curr);
        return curr;
    }
    
    private TreeNode dfsRight(TreeNode curr) {
        if (curr.left == null && curr.right == null)
            return curr;
        
        // First find the new root
        TreeNode root = curr;
        while (root.left != null)
            root = root.left;
        
        this.upsideDown(curr);
        return root;
    }
    
    private void upsideDown(TreeNode curr) {
        TreeNode left = curr.left, right = curr.right;
        if (curr.left != null)
            left = this.dfsLeft(curr.left);
        
        if (curr.right != null)
            right = this.dfsRight(curr.right);
        
        // Upside down
        left.right = curr;
        left.left = right;
        
        curr.left = null;
        curr.right = null;
    }
}

以下是C++的题解代码实现(实际题目的答案)。

/**
 * 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 {
public:
    TreeNode* upsideDownBinaryTree(TreeNode* root) {
        if (!root)
            return root;
        
        // First find the new root
        TreeNode *new_root = root;
        while (new_root->left)
            new_root = new_root->left;
        
        this->_Dfs(root);
        return new_root;
    }

private:
    TreeNode* _Dfs(TreeNode *curr) {
        if (!curr->left && !curr->right)
            return curr;

        TreeNode *left = curr->left, *right = curr->right;
        if (curr->left)
            left = this->_Dfs(curr->left);
        
        // Upside down
        left->right = curr;
        left->left = right;
        
        curr->left = nullptr;
        curr->right = nullptr;
        
        return curr;
    }
};

Search

    Table of Contents