题目
解题分析
呓语:欧耶,逐渐掌握二叉树了吗?这么快吗? 哈哈哈,开心
正经一点,正经一点,这个题目看上去是很复杂,但是只要按照递归的套路去写,是一定可以写出来的。
①递归形式
flipTree(root)
其最终的返回值应该是翻转之后的tree
②单层递归情况
所谓的翻转,就是左子树和右子树调换位置。但是,这里要返回一个新的子树才对。
所以单层递归为:
let node = new TreeNode();
node.val = root.val;
root.left = flipTree(root.right);
root.right = flipTree(root.left);
③ 跳出递归条件
按照下面TreeNode的形式,当root为空的时候,返回null;
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
整合一下以上三步,整体代码为:
/**
* @param {TreeNode} root
* @return {TreeNode}
*/
var invertTree = function(root) {
let flipTree=(root)=>{
if(!root) return null;
let node = new TreeNode();
node.val = root.val;
root.left = flipTree(root.right);
root.right = flipTree(root.left);
return root;
}
return flipTree(root);
};
优秀题解分析
我的做法中,为了实现左右子树的调换,用了一个新的node去存储相关内容。
但实际上,是可以通过一个中间变量先实现左右子树的调换,再进行遍历。
即:
/**
* @param {TreeNode} root
* @return {TreeNode}
*/
var invertTree = function(root) {
let flipTree=(root)=>{
if(!root) return null;
let node = new TreeNode();
// 左右子树调换
node = root.left;
root.left = root.right;
root.right = node;
// 递归遍历
flipTree(root.right);
flipTree(root.left);
return root;
}
return flipTree(root);
};
不过从时间复杂度是没有什么差别的,都需要遍历每一个节点,为O(n)。
空间复杂度引用官方理解:
使用的空间由递归栈的深度决定,它等于当前节点在二叉树中的高度。在平均情况下,二叉树的高度与节点个数为对数关系,即 O(log N)。而在最坏情况下,树形成链状,空间复杂度为 O(N)。
但空间复杂度就不一样了,我写的是自顶向下的方式,先递归再求解,占用辅助空间多。
先交换左右子树是,自底向上,先求解再递归,占用辅助空间少。
总结
当逐渐掌握解题思路之后,还是要考虑更优解法的~