一、力扣题102. 二叉树的层序遍历
给你二叉树的根节点 root
,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:[[3],[9,20],[15,7]]
示例 2:
输入:root = [1] 输出:[[1]]
示例 3:
输入:root = [] 输出:[]
提示:
- 树中节点数目在范围
[0, 2000]
内 -1000 <= Node.val <= 1000
层序遍历符合队列先进先出的特性,适合用队列来实现。先将二叉树的一层放入队列,将这一层的节点从队列中取出放入数组的同时,将这些节点的子节点放入队列,把这一层取光后,队列中存放的就是下一层的节点了。
此时就需要一个变量来确定每一层的遍历次数。在队列开始将一层的节点取出来之前,先用$size 记录这一层的节点数,然后遍历 $size 次,就把这一层的节点全取出来了。然后 $size 再继续记录下一层的节点数。
同时每一层的值都要单独用一个数组存放,定义存放一层的值的数组为 $arr , 所以遍历每一层之前都要把 $arr 重新置空。
function levelOrder($root) {
$queue = new splQueue();
if($root) $queue->enqueue($root);
$result = [];
while(!$queue->isEmpty()) {
$size = $queue->count();
$arr = [];
for($i = 0; $i < $size; $i++) {
$cur = $queue->dequeue();
$arr[] = $cur->val;
if($cur->left) $queue->enqueue($cur->left);
if($cur->right) $queue->enqueue($cur->right);
}
$result[] = $arr;
}
return $result;
}
之后还做了卡哥推荐的其他类似题目,篇幅原因就不在这里放题目内容了:
107.二叉树的层次遍历II
将以上层序遍历获取到的数组反转一下就可以了
function levelOrderBottom($root) {
$queue = new splQueue();
if($root) $queue->enqueue($root);
$result = [];
while(!$queue->isEmpty()) {
$size = $queue->count();
$arr = [];
for($i = 0; $i < $size; $i++) {
$cur = $queue->dequeue();
$arr[] = $cur->val;
if($cur->left) $queue->enqueue($cur->left);
if($cur->right) $queue->enqueue($cur->right);
}
$result[] = $arr;
}
$result = array_reverse($result);
return $result;
}
199.二叉树的右视图:
层序遍历中把子节点放入队列的顺序改了一下,换成先放入右节点再放入左节点,这样队列中每一层就都是从右到左遍历的值了,直接取第一个值就好。
function rightSideView($root) {
$queue = new splQueue();
if($root) $queue->enqueue($root);
$result = [];
while(!$queue->isEmpty()) {
$size = $queue->count();
$result[] = $queue->bottom()->val;
for($i = 0; $i < $size; $i++) {
$cur = $queue->dequeue();
$arr[] = $cur->val;
if($cur->right) $queue->enqueue($cur->right);
if($cur->left) $queue->enqueue($cur->left);
}
}
return $result;
}
637.二叉树的层平均值
function averageOfLevels($root) {
$queue = new splQueue();
if($root) $queue->enqueue($root);
$result = [];
while(!$queue->isEmpty()) {
$size = $queue->count();
$arr = [];
for($i = 0; $i < $size; $i++) {
$cur = $queue->dequeue();
$arr[] = $cur->val;
if($cur->left) $queue->enqueue($cur->left);
if($cur->right) $queue->enqueue($cur->right);
}
if($arr) $result[] = round(array_sum($arr) / count($arr), 5);
}
return $result;
}
429.N叉树的层序遍历
function levelOrder($root) {
$queue = new splQueue();
if($root) $queue->enqueue($root);
$result = [];
while(!$queue->isEmpty()) {
$size = $queue->count();
$arr = [];
for($i = 0; $i < $size; $i++) {
$cur = $queue->dequeue();
$arr[] = $cur->val;
for($j = 0; $j < count($cur->children); $j++) {
if($cur->children[$j]) {
$queue->enqueue($cur->children[$j]);
}
}
}
$result[] = $arr;
}
return $result;
}
515.在每个树行中找最大值
function largestValues($root) {
$queue = new splQueue();
if($root) $queue->enqueue($root);
$result = [];
while(!$queue->isEmpty()) {
$size = $queue->count();
$max = PHP_INT_MIN;
while($size--) {
$cur = $queue->dequeue();
if($cur->val > $max) $max = $cur->val;
if($cur->left) $queue->enqueue($cur->left);
if($cur->right) $queue->enqueue($cur->right);
}
$result[] = $max;
}
return $result;
}
116.填充每个节点的下一个右侧节点指针
public function connect($root) {
$queue = new splQueue();
if($root) $queue->enqueue($root);
while(!$queue->isEmpty()) {
$size = $queue->count();
while($size) {
$size--;
$cur = $queue->dequeue();
if($size) {
$cur->next = $queue->bottom();
}
if($cur->left) $queue->enqueue($cur->left);
if($cur->right) $queue->enqueue($cur->right);
}
}
return $root;
}
104.二叉树的最大深度
111.二叉树的最小深度
以上这两题之后的训练里有,就不放了。
二、力扣题226. 翻转二叉树
给你一棵二叉树的根节点 root
,翻转这棵二叉树,并返回其根节点。
示例 1:
输入:root = [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1]
示例 2:
输入:root = [2,1,3] 输出:[2,3,1]
示例 3:
输入:root = [] 输出:[]
提示:
- 树中节点数目范围在
[0, 100]
内 -100 <= Node.val <= 100
这道题说到底就是把二叉树里每个节点的左右节点都交换一下,使用前中后序、层序遍历都可以。
方法一:递归法
function invertTree($root) {
if(!$root) return;
$temp = $root->left;
$root->left = $root->right;
$root->right = $temp;
if($root->left) $this->invertTree($root->left);
if($root->right) $this->invertTree($root->right);
return $root;
}
方法二:迭代法
function invertTree($root) {
$stack = new splStack();
if($root) $stack->push($root);
while(!$stack->isEmpty()) {
$cur = $stack->pop();
$temp = $cur->left;
$cur->left = $cur->right;
$cur->right = $temp;
if($cur->left) $stack->push($cur->left);
if($cur->right) $stack->push($cur->right);
}
return $root;
}
方法三:层序遍历
function invertTree($root) {
$queue = new splQueue();
if($root) $queue->enqueue($root);
while(!$queue->isEmpty()) {
$size = $queue->count();
while($size--) {
$cur = $queue->dequeue();
$temp = $cur->left;
$cur->left = $cur->right;
$cur->right = $temp;
if($cur->left) $queue->enqueue($cur->left);
if($cur->right) $queue->enqueue($cur->right);
}
}
return $root;
}
三、力扣题101. 对称二叉树
给你一个二叉树的根节点 root
, 检查它是否轴对称。
示例 1:
示例 2:
输入:root = [1,2,2,null,3,null,3] 输出:false
提示:
- 树中节点数目在范围
[1, 1000]
内 -100 <= Node.val <= 100
这道题一开始想不到解法,不知道怎么才能把左子树和右子树的节点一一对应对比。然后去看了题解,才知道了成对对比的方法,就是 left -> left 和 right -> right 对应, left -> right 和 right -> left 对应。
递归的话就是分别传入这两对参数到两个递归函数里,然后拿到返回值确定真假。
方法一:递归法
function isSymmetric($root) {
return $this->result($root->left, $root->right);
}
function result($left, $right) {
if(!$left && !$right) {
return true;
} else if(!$left || !$right) {
return false;
} else if($left->val != $right->val) {
return false;
}
$leftRes = $this->result($left->left, $right->right);
$rightRes = $this->result($left->right, $right->left);
return $leftRes && $rightRes;
}
方法二:迭代法
使用栈的话就每次把成对的参数放一起入栈,出栈时出两个一起对比就可以了。
function isSymmetric($root) {
$stack = new splStack();
$stack->push($root->left);
$stack->push($root->right);
while(!$stack->isEmpty()) {
$right = $stack->pop();
$left = $stack->pop();
if($right === null && $left === null) continue;
if($right === null || $left === null) return false;
if($right->val != $left->val) return false;
$stack->push($left->left);
$stack->push($right->right);
$stack->push($left->right);
$stack->push($right->left);
}
return true;
}
方法三:层序遍历
层序遍历也是同样的逻辑,将成对的参数放入队列,再成对取出对比。
function isSymmetric($root) {
$queue = new splQueue();
$queue->enqueue($root->left);
$queue->enqueue($root->right);
while(!$queue->isEmpty()) {
$left = $queue->dequeue();
$right = $queue->dequeue();
if($left === null && $right === null) continue;
if($left === null || $right === null || $left->val != $right->val) return false;
$queue->enqueue($left->left);
$queue->enqueue($right->right);
$queue->enqueue($left->right);
$queue->enqueue($right->left);
}
return true;
}