题目
操作给定的二叉树,将其变换为源二叉树的镜像。
解析
预备知识
我们需要理解二叉树的镜像是什么意思,画图解释更加直观!
思路一
对于这种问题,还是画图比较清晰直观,既然我们想获得二叉树的镜像,那么根节点的两边必然是反过来的啊。所以第一步我们交换左右子树。
这时我们发现交换后的左右子树的子节点还是保持原来的顺序,所以需要我们去交换左右子树自己的左右子树。
综上,我们的大问题已经逐步转化为了相同的子问题,第一步交换根节点的左右子树,之后交换左右子树自己的左右子树,这样的操作除了操作对象不同,但是操作步骤是一样,所以非常时候采用递归来做,我们用递归方式来递归交换各个左右子树。
/**
* 递归实现
* 关键就在于把大问题转化为子问题即可
* @param root
*/
public static void Mirror1(TreeNode root) {
if(root != null) {
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
Mirror1(root.left);
Mirror1(root.right);
}
}
思路二
其实如果理解了思路一,我们可以发现只要采取某一种遍历方式去遍历树的所有的非叶子节点,然后交换它的左右子树,当遍历结束,即可得到二叉树的镜像。
仔细观察思路一的代码,这不就是递归实现的先序遍历的变形嘛!。当然我们不必非得采用先序,中序或者后序遍历节点。其实DFS或者BFS都可以的,只要能够保证所有的非叶子节点都访问一次即可。以下我们采用基于栈的DFS来遍历(基于队列的BFS感兴趣的可以自行尝试哦):
/**
* 非递归实现, 借助栈或者列表遍历树中每一个非叶子节点
* 交换其左右子树即可
* @param root
*/
public static void Mirror2(TreeNode root) {
if(root == null) {
return;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()) {
TreeNode node = stack.pop();
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
if(node.left != null) {
stack.push(node.left);
}
if(node.right != null) {
stack.push(node.right);
}
}
}
总结
这种新的概念的题目,当没有头绪的时候,画图走过程就是解题的钥匙!