题目
思路
所谓层序遍历,就是一层一层的遍历。
输出的结果是这样:二维数组,二维数组中的一维数组是这层节点的value。
借助了队列的结构。
每个节点弹出时,把自己的孩子节点加到队列里面。
如果只是单纯地把孩子加入,那么在队列中就会出现这个问题:队列中的节点,哪些是第n层的节点?哪些是第n-1层的节点?
所以在节点加入的时候,要用size进行记录,size是当前节点层的节点个数。
核心
- 节点弹出,并记录节点
- push节点的左右孩子
- 两层while循环
-
- 外层的while循环由queue内的节点数控制,无节点时停止
- 内层的while循环由size控制,本层的节点遍历完停止
var levelOrder = function(root) {
if(root == null) {
return [];
}
let queue = [];
let arr = [];
let res = [];
let size = 0;
queue.push(root);
while(queue.length != 0) {
size = queue.length;
while(size-- > 0) {
let node = queue.shift();
// 注意这里,push进去的应该是个值,而不是整个节点
arr.push(node.val);
if(node.left != null) {
queue.push(node.left);
}
if(node.right != null) {
queue.push(node.right);
}
}
res.push(arr);
arr = [];
}
return res;
};
思路
前序遍历,交换每个节点的左右孩子
var invertTree = function(root) {
// []的这种情况怎么处理
if (root == null) {
return null;
}
let node = root.left;
root.left = root.right;
root.right = node;
invertTree(root.left);
invertTree(root.right);
return root;
};
题目
解法一:
失败。
超出时间限制
var isSymmetric = function(root) {
let queue = [];
let size = 0;
queue.push(root);
while(queue.length != 0) {
size = queue.length;
while(size-- > 0) {
let node = queue.shift();
queue.push(node.left);
queue.push(node.right);
}
let i = 0;
let j = queue.length - 1;
while(i < j) {
// 1.两个都是null
// 2.一个null,一个不是null
// 3.两个都不是null
if(queue[i] == null && queue[j] == null){
continue;
}
if(queue[i] == null || queue[j] == null){
return false;
}
if(queue[i].val != queue[j].val) {
return false;
}
i++;
j--;
}
}
解法二:
迭代法
判断是否对称,其实是比较每一层的对应位置节点值是否相等。
因为这个操作是在“每一层”中进行的,所以很自然的想到在层序遍历的基础上做修改。
这里其实和层序遍历很相似,不同的地方是:
- 层序遍历弹出一个节点,放入本节点的左右节点;而本题是弹出两个节点,放入两个节点的左右节点共四个节点
- 层序遍历放入节点的顺序是从左到右依次放入;而本题是先放入外侧两个节点,再放入内侧的两个节点。
- 本题需要比较弹出的两个节点。
var isSymmetric = function(root) {
let queue = [];
queue.push(root.left);
queue.push(root.right);
while(queue.length != 0) {
let leftNode = queue.shift();
let rightNode = queue.shift();
// 两个节点都是空,只能说用continue,跳过当前这次的循环。
// 那为什么下面就可以return false呢?
// 因为一个反例就可以推倒所有
if(leftNode == null && rightNode == null) {
continue;
}else if(leftNode != null && rightNode == null) {
return false;
}else if(leftNode == null && rightNode != null) {
return false;
}else if(leftNode.val != rightNode.val) {
return false;
}
queue.push(leftNode.left);
queue.push(rightNode.right);
queue.push(leftNode.right);
queue.push(rightNode.left);
}
return true;
};
递归法
- 后序遍历,收集信息
- 收集以下的信息:
左子树、右子树-外侧是否相等
左子树、右子树-内侧是否相等
- 整合
外侧、内侧都相等,对称。
var compare = function(leftNode, rightNode) {
if(leftNode == null && rightNode == null) {
return true;
}else if(leftNode == null || rightNode == null) {
return false;
}else if(leftNode.val != rightNode.val) {
return false;
}
let outside = compare(leftNode.left, rightNode.right);
let inside = compare(leftNode.right, rightNode.left);
return outside && inside;
}
难点:
- 这道题的参数应该是两个,这样才能比较
- 以往的终止条件是到叶子节点;本题终止条件是两个节点的比较