1.问题
给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
示例 1:
输入: [1,2,3,null,5,null,4]
输出: [1,3,4]
示例 2:
输入: [1,null,3]
输出: [1,3]
示例 3:
输入: []
输出: []
提示:
- 二叉树的节点个数的范围是 [0,100]
- -100 <= Node.val <= 100
2.解题思路
经历过前面几篇关于二叉树的层序遍历算法之后(参见102.二叉树的层序遍历,107.二叉树的层序遍历II),非常容易的就可以通过这种算法解答此题,基本思想就是围绕队列性质,广度优先算法解决。当然,深度优先算法也是可以解决的。
2.1 广度优先(BFS)
利用队列,遍历每层节点,并记录每层最后一个元素,直到遍历完最后一层,即可得到结果。访问顺序如下图所示:
红色结点自上而下组成答案,边缘以访问顺序标号。
复杂度:
- 时间复杂度: O(N),每个节点都入队出队了 1 次。
- 空间复杂度: O(N),使用了额外的队列空间。
2.2 深度优先(DFS)
1)优先访问右子树,即访问顺序为:根-右-左;
2)如果当前节点所在深度还没有出现在res里(因为一层就一个节点),说明在该深度下当前节点是第一个被访问的节点,因此将当前节点加入res中。
if len(res) < depth:
res.append(root.val)
# 遍历右子树
if root.right:
dfs(root.right, depth + 1, res)
# 遍历左子树
if root.left:
dfs(root.left, depth + 1, res)
复杂度:
- 时间复杂度: O(N),每个节点都访问了 1 次。
- 空间复杂度: O(N),因为这不是一棵平衡二叉树,二叉树的深度最少是 logN, 最坏的情况下会退化成一条链表,深度就是N,因此递归时使用的栈空间是 O(N) 的。
3.代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
/**
广度优先
1.利用层序遍历思想,统计每层最后一个元素,即为答案
2.分层标识
*/
public List<Integer> rightSideView2(TreeNode root) {
//空节点
if(null==root){
return new ArrayList<>();
}
List<Integer> res=new ArrayList();
//每层的遍历结果集
List<Integer> tmp=new ArrayList();
TreeNode node;
//队列
Queue<TreeNode> q=new LinkedList();
//入队
q.add(root);
//分层标识
q.add(null);
while(!q.isEmpty()){
node=q.poll();
if(null!=node){
tmp.add(node.val);
//左右子树入队
if(null!=node.left){
q.add(node.left);
}
if(null!=node.right){
q.add(node.right);
}
}
//否层,该层遍历完毕
else{
if(!tmp.isEmpty()){
//收集每层最后一个元素
res.add(tmp.get(tmp.size()-1));
tmp=new ArrayList();
q.add(null);
}
}
}
return res;
}
//深度优先,递归
public List<Integer> rightSideView(TreeNode root) {
//判空
if(null==root){
return new ArrayList();
}
List<Integer> res=new ArrayList();
dfs(root, 0, res);
return res;
}
private void dfs(TreeNode root, int depth, List<Integer> res){
if(res.size()==depth){
res.add(root.val);
}
//左右子树,先遍历右子树,然后左子树
if(null!=root.right){
dfs(root.right, depth+1, res);
}
if(null!=root.left){
dfs(root.left, depth+1, res);
}
}
}