226 翻转二叉树
思路
- 此题可以使用多种方法:一方面选择前序,后序,中序,层序等。一方面选择递归方式或者迭代方式。总体思想就是:将二叉树全部遍历一遍,然后翻转
解决问题中
-
我选择的方式:递归版本前序遍历
function invertTree(root){ // 作用域1 function invertNode(left,right){ // 作用域2 let temp = left left = right right = temp // 把我难住的地方:需要将交换之后的值赋值给root节点 root.left = left root.right = right } invertNode(root.left,root.right) // 调用交换函数,使得节点的值两两交换 invertTree(root.left) // 将left左子树进行递归处理 invertTree(root.right) // 将right右子树进行递归处理 return root }
疑难点: 这道题中把我难住的地方,是交换函数中的后面两步,不明白为什么要赋值给root,我以为它多此一举,但是如果没有这两句的话 ,结果并不会发生翻转。
想了一下,也许这跟引用数据类型和简单数据类型的赋值拷贝的知识有关。树就像对象中包着对象,交换函数中好像是已经将他们的值交换成功了,但是由于左右节点是处于root这个对象中的,所以函数外部再次引用他们的时候发现,值并没有发生改变。所以才有了需要 将交换后的值赋值给节点的操作。
但是,我再次想一想,上面的想法是不对的,用简单的例子测试:
let a = 1,b = 2
function ver(l,r){
let t = l
l =r
r = t
return [l,r]
}
console.log(ver(a,b)) //结果是[2,1] 结果正确
但是一旦在交换函数的外部再次调用这两个变量时,发现并没有改变
console.log(a,b) // 1,2
let a = {
a1:1,
a2:2
}
function ver(l,r){
let t = l
l =r
r = t
return [l,r]
}
console.log(ver(a.a1,a.a2)) //结果是[2,1]
console.log(a.a1,a.a2) // 依旧是 1,2
原因: 在交换函数之外调用变量时,JavaScript是先从调用位置的当前作用域开始查找的,很明显当前作用域是全局作用域 ,所以找到的是 1,2 。外部作用域是不能调用内部作用域中的变量。
解决: 代码中找到的left right节点,是作用域1 中的。不是交换函数 ,也就是作用域2 中交换后的。 因为在交换函数中被赋值的 left right 是在作用域1找到的,所以复制后作用域1中的left right才会改变。所以,在交换函数中,需要进行节点的赋值这一步骤。