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. For example: Given a binary tree {1,2,3,4,5}, 1 / 2 3 / 4 5 return the root of the binary tree [4,5,2,#,#,3,1]. 4 / 5 2 / 3 1
这题第一眼看上去觉得没头绪,不知道怎么上下翻转和左右翻转。但在纸上画几个例子就清楚了。所有的右子树要么为空、要么就是叶子节点且有左子树存在。
那么原来的数一直沿左子树走下去最左的那个节点就是新树的根节点。
这道题最关键在于想到要用递归去做!这种树的结构、父子两层节点关系的问题多半都要用递归去做。这是大方向。我最开始想到用stack, 用hashmap来存然后用迭代都有点复杂。递归就很简单。
一旦确定递归,问题就迎刃而解了,就是一直往左走到叶子节点,返回该点作为新的根节点newRoot,定义newRoot.left, newRoot.right, 再返回newRoot.right作为上一层的newRoot。
注意递归函数最终返回的节点并非我们所求,如上图返回1节点,而我们需要新树的root节点:节点4. 所以在递归里加一个argument,ArrayList<TreeNode>, 来包裹新root节点当找到它时。这是java函数参数传递问题,如果直接用TreeNode作为argument, 传的是引用,函数里引用所指的地址发生改变,不会让函数外的引用所指的地址改变
1 public class Solution { 2 public TreeNode UpsideDownBinaryTree(TreeNode root) { 3 if (root == null) return null; 4 ArrayList<TreeNode> res = new ArrayList<TreeNode>(); 5 res.add(null); 6 helper(root, res); 7 return res.get(0); 8 } 9 10 public TreeNode helper(TreeNode root, ArrayList<TreeNode> res) { 11 if (root.left == null) { 12 res.set(0, root); 13 return root; 14 } 15 TreeNode newRoot = helper(root.left, res); 16 newRoot.left = root.right; 17 newRoot.right = root; 18 return newRoot.right; 19 } 20 }
Best approach: do it in place
1 /** 2 * Definition for a binary tree node. 3 * public class TreeNode { 4 * int val; 5 * TreeNode left; 6 * TreeNode right; 7 * TreeNode(int x) { val = x; } 8 * } 9 */ 10 class Solution { 11 public TreeNode upsideDownBinaryTree(TreeNode root) { 12 if(root == null || root.left == null) { 13 return root; 14 } 15 16 TreeNode newRoot = upsideDownBinaryTree(root.left); 17 root.left.left = root.right; // node 2 left children 18 root.left.right = root; // node 2 right children 19 root.left = null; 20 root.right = null; 21 return newRoot; 22 } 23 }