package com.leetcode.trees;
import java.util.Stack;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
/**
* Level: Medium
* Problem Link: https://leetcode.com/problems/binary-tree-upside-down/
* Problem Description:
* Given a binary tree where all the right nodes are either leaf nodes with a sibling (a left node that shares the
* same parent node) or empty, flip it upside down and turn it into a tree where the original right nodes turned into
* left leaf nodes. Return the new root.
*
* Example:
* Input: [1,2,3,4,5]
*
* 1
* / \
* 2 3
* / \
* 4 5
*
* Output: return the root of the binary tree [4,5,2,#,#,3,1]
*
* 4
* / \
* 5 2
* / \
* 3 1
*
* Clarification:
* Confused what [4,5,2,#,#,3,1] means? Read more below on how binary tree is serialized on OJ. The serialization of
* a binary tree follows a level order traversal, where '#' signifies a path terminator where no node exists below.
*
* Here's an example:
*
* 1
* / \
* 2 3
* /
* 4
* \
* 5
*
* The above binary tree is serialized as [1,2,3,#,#,4,#,#,5].
*
* @author rampatra
* @since 2019-08-04
*/
public class BinaryTreeUpsideDown {
/**
* The solution is simple, every node (except the root) on the left of the tree would have its parent's right child
* as it's left child and parent as its right child. That's all you have to do to flip the tree upside down.
*
* Time Complexity: O(h)
* Space Complexity: O(h)
* where,
* h = height of the tree
*
* Runtime: 1 ms.
*
* @param root
* @return
*/
public static TreeNode upsideDownBinaryTreeUsingStack(TreeNode root) {
if (root == null) return null;
TreeNode curr = root;
TreeNode currParent;
TreeNode newRoot = null;
// using stack to keep track of the parent node
Stack stack = new Stack<>();
while (curr != null) {
stack.add(curr);
curr = curr.left;
}
while (!stack.empty()) {
curr = stack.pop();
currParent = stack.empty() ? null : stack.peek();
if (newRoot == null) newRoot = curr;
if (currParent != null) {
curr.left = currParent.right;
curr.right = currParent;
} else {
curr.left = null;
curr.right = null;
}
}
return newRoot;
}
/**
* The solution is simple, every node (except the root) on the left of the tree would have its parent's right child
* as it's left child and parent as its right child. That's all you have to do to flip the tree upside down.
*
* Time Complexity: O(h)
* Space Complexity: O(h)
* where,
* h = height of the tree
*
* Runtime: 0 ms.
*
* @param node
* @return
*/
public static TreeNode upsideDownBinaryTree(TreeNode node) {
if (node == null || node.left == null) return node;
// go to the last node on the extreme left branch
TreeNode newRoot = upsideDownBinaryTree(node.left);
// do the node changes as you backtrack
node.left.left = node.right;
node.left.right = node;
// clean up
node.left = null;
node.right = null;
return newRoot;
}
public static void main(String[] args) {
/*
Binary Tree
1
/ \
2 3
/ \
4 5
*/
TreeNode tree = new TreeNode(1);
tree.left = new TreeNode(2);
tree.right = new TreeNode(3);
tree.left.left = new TreeNode(4);
tree.left.right = new TreeNode(5);
/*
Upside Down Binary Tree
4
/ \
5 2
/ \
3 1
*/
TreeNode upsideDownTree = upsideDownBinaryTreeUsingStack(tree);
assertEquals(4, upsideDownTree.val);
assertEquals(5, upsideDownTree.left.val);
assertEquals(2, upsideDownTree.right.val);
assertEquals(1, upsideDownTree.right.right.val);
assertEquals(3, upsideDownTree.right.left.val);
assertNull(upsideDownTree.right.right.left);
assertNull(upsideDownTree.right.right.right);
/******************************
*
* Test for the recursive method
*
******************************/
/*
Binary Tree
1
/ \
2 3
/ \
4 5
*/
tree = new TreeNode(1);
tree.left = new TreeNode(2);
tree.right = new TreeNode(3);
tree.left.left = new TreeNode(4);
tree.left.right = new TreeNode(5);
/*
Upside Down Binary Tree
4
/ \
5 2
/ \
3 1
*/
upsideDownTree = upsideDownBinaryTree(tree);
assertEquals(4, upsideDownTree.val);
assertEquals(5, upsideDownTree.left.val);
assertEquals(2, upsideDownTree.right.val);
assertEquals(1, upsideDownTree.right.right.val);
assertEquals(3, upsideDownTree.right.left.val);
assertNull(upsideDownTree.right.right.right);
assertNull(upsideDownTree.right.right.left);
}
}