题目描述:
给定一个二叉树的 根节点 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
需要注意的一点是:返回的数组中应该包括树中最右侧的节点和下方没有被右侧节点挡住的左侧节点。
这道题有两种解题方法,第一种是利用树的深度遍历(先序遍历),第二种是用树的广度遍历(层序遍历)。
先序遍历
因为先序遍历是从根节点到左子树,再到右子树依次访问树的节点的,可以想见,如果我们用一个数组来存储遍历的结果,用变量 i 来控制数组在递归中的下标,那么递归的每一层变量 i 的值都是相同的,那么树中较长的子树远离根节点的节点(没有被右侧节点盖住的下方节点)就会被保存在数组中,而被右侧节点挡住的节点,在最后都会被最右侧节点覆盖。
代码:
int rightView(struct TreeNode* root, int* a, int i)
{
if(!root)
return 0;
a[i] = root -> val;
int left = rightView(root -> left, a, i + 1);
int right = rightView(root -> right, a, i + 1);
return fmax(left, right) + 1;
}
int* rightSideView(struct TreeNode* root, int* returnSize){
*returnSize = 0;
if(!root)
return NULL;
int* a = (int*)malloc(sizeof(int) * 100);
*returnSize = rightView(root, a, 0);
return a;
}
当然,在递归函数中,我们也要返回树的高度作为数组的大小。
层序遍历
第二种方法是利用树的层序遍历,在树的一层遍历完后,记录最后一个被访问的节点的值,但在普通的层序遍历中,循环不是一层一层来做的,而是一个节点一个节点来做的,所以普通的层序遍历我们无法知道是不是已经完成了一层的遍历。
struct TreeNode* tarray[101];
int front = 0, rear = 0;
tarray[rear++] = root;
while(front != rear)
{
struct TreeNode* tnode = tarray[front++];
if(tnode -> left)
tarray[rear++] = tnode -> left;
if(tnode -> right)
tarray[rear++] = tnode -> right;
}
之所以会这样是因为在循环中rear会因为不断加入下一层节点而不断变化,这就需要我们引入一个新的控制变量head,来记录下加入下一层节点之前rear的值,也就是当前层最后一个节点的下标。
struct TreeNode* tarray[101];
int* array = (int*)malloc(sizeof(int) * 100);
int front = 0, rear = 0, head;
tarray[rear++] = root;
while(front != rear)
{
head = rear;
struct TreeNode* tnode;
while(front != head)
{
tnode = tarray[front++];
if(tnode -> left)
tarray[rear++] = tnode -> left;
if(tnode -> right)
tarray[rear++] = tnode -> right;
}
}
在大循环中套入了第二层循环,这个循环从front开始head结束,来进行一层遍历。
上图的例子中,front从0开始,head记录没有进入第二层循环的rear值1(第一层最后一个节点点下标加一),第二层循环结束后,rear变为了3(第二层最后一个节点下标加一),接着进入下一层循环,如此重复,直到front与rear值相等了,说明没有新的元素进入队列,遍历完毕。
代码:
int* rightSideView(struct TreeNode* root, int* returnSize){
*returnSize = 0;
if(!root)
return NULL;
struct TreeNode* tarray[101];
int* array = (int*)malloc(sizeof(int) * 100);
int front = 0, rear = 0, head;
tarray[rear++] = root;
while(front != rear)
{
head = rear;
struct TreeNode* tnode;
while(front != head)
{
tnode = tarray[front++];
if(tnode -> left)
tarray[rear++] = tnode -> left;
if(tnode -> right)
tarray[rear++] = tnode -> right;
}
array[(*returnSize)++] = tnode -> val;
}
return array;
}
在完成一层的节点访问后,tnode节点记录了最后一个被访问的节点,就是该层中最右端节点,直接将该结点的值记录到array数组中。