Start learning free

LESSON 445 OF 573 · BINARY TREES

Binary Tree Right Side View in Go: Level Order with a Queue

Practice O(n) Read the full explanation

Given the root of a binary tree, imagine yourself standing on its right side. Return the values of the nodes you can see, ordered from top to bottom.

From the right you see exactly one node on each level: the rightmost node of that level, the last one when you read the level from left to right. It can belong to the left subtree, when the right subtree doesn't reach that deep. An empty tree shows nothing.

The trees below are written in level order (top to bottom, left to right), with nil for a missing child.

 

Example 1:

    1
   / \
  2   3
   \   \
    5   4

Input: root = [1,2,3,nil,5,nil,4]
Output: [1,3,4]
Explanation: The first level is just 1. On the second level, 3 hides 2. On the third level, 4 hides 5.

Example 2:

      1
     / \
    2   3
   /
  4

Input: root = [1,2,3,4]
Output: [1,3,4]
Explanation: The third level has only 4. It is in the left subtree, but nothing stands to its right, so you see it.

Example 3:

Input: root = []
Output: []
Explanation: An empty tree has no levels, so you see no nodes.

 

Constraints:

  • The number of nodes in the tree is in the range [0, 100].
  • -100 <= Node.val <= 100
  • Values may repeat.

Note:

The tutorial walks the tree level by level with a queue. The queue starts with the root. At the start of each round it holds exactly one level: count its nodes, take them out one by one from the front, and put each node's children (left, then right) at the back, where they wait for the next round. The last node taken out in a round is the rightmost node of its level: that is the one you see.

Each node enters and leaves the queue once, so the time is O(n) for a tree of n nodes. The queue holds at most about two levels at a time, which is O(n) extra space in the worst case.

STEP 1 OF 11
    Ctrl + Enter to check

    GO · BINARY TREES

    Binary Tree Right Side View in Go, explained

    Problem overview

    The function rightSideView receives the root of a binary tree and returns the values of the nodes you would see standing on its right side, from top to bottom. The lesson provides the TreeNode type, a struct with an integer Val and two pointers, Left and Right, which are nil when a child is missing.

    From the right you see exactly one node per level: the rightmost one. For the tree with root 1, children 2 and 3, and grandchildren 5 (under 2) and 4 (under 3), the answer is [1 3 4]. On the second level 3 hides 2, and on the third level 4 hides 5.

    The rightmost node of a level is not always a right child. In the tree with root 1, children 2 and 3, and a single grandchild 4 under 2, the answer is also [1 3 4]: nothing stands to the right of 4, so it is visible even though it belongs to the left subtree. An empty tree returns an empty slice.

    Approach: walk the tree one level at a time

    A tempting shortcut is to follow only the right children from the root. It works when the right side reaches the bottom of the tree, and fails otherwise: on the second tree above it gives [1 3] and misses the 4.

    The reliable idea is a level order traversal. Keep a queue of nodes waiting to be visited, and process it in rounds. At the start of each round the queue holds exactly one level of the tree. Count the nodes in it, take that many out from the front, and add each node's children to the back, left first and then right. The children belong to the next level, so they wait behind the current one. The last node taken out in a round is the rightmost node of that level, so its value goes into the result.

    Every node enters and leaves the queue once, so the work is proportional to the number of nodes. A depth-first search that remembers the depth can also solve the problem, but this lesson uses the queue.

    Tracing the first example

    Printing each round's nodes in the order they leave the queue for the first tree gives:

    level 1 [1]
    level 2 [2 3]
    level 2 [5 4]

    The last value of each round, 1, 3 and 4, is the answer.

    Step by step

    1. Create result as an empty []int. It collects one value per level.
    2. Handle the empty tree. If root == nil, return result at once, because the queue needs a first node to start from.
    3. Create the queue as a slice of node pointers holding the root. The first element is the front, and append adds at the back.
    4. Loop while the queue is not empty. Go has no while, so for len(queue) > 0 plays that role. Each pass handles one whole level.
    5. Store len(queue) in levelSize before touching the queue. At that moment it holds exactly one level.
    6. Loop i from 0 to levelSize - 1. Children added during this loop belong to the next level, and counting up to the saved size stops the loop before it reaches them.
    7. Take the next node from queue[0] and drop it with queue = queue[1:].
    8. Record the last node of the level. When i == levelSize-1, append node.Val to result.
    9. Enqueue the left child if it is not nil.
    10. Enqueue the right child the same way. Adding left before right keeps each level in left-to-right order.
    11. Return result after the loops.

    The solution in Go

    func rightSideView(root *TreeNode) []int {
    	result := []int{}
    	if root == nil {
    		return result
    	}
    	queue := []*TreeNode{root}
    	for len(queue) > 0 {
    		levelSize := len(queue)
    		for i := 0; i < levelSize; i++ {
    			node := queue[0]
    			queue = queue[1:]
    			if i == levelSize-1 {
    				result = append(result, node.Val)
    			}
    			if node.Left != nil {
    				queue = append(queue, node.Left)
    			}
    			if node.Right != nil {
    				queue = append(queue, node.Right)
    			}
    		}
    	}
    	return result
    }

    The Go details worth a closer look:

    • A slice as a queue. queue[1:] is a slice that starts one element later. It does not copy anything, so removing from the front is cheap. append adds at the end and may allocate a bigger backing array when there is no room.
    • Pointers in the slice. The queue has type []*TreeNode, so it stores pointers to the nodes, not copies of them. Comparing a child with nil tells you whether it exists.
    • Reassigning after append. append returns the slice that may be longer, so you must store it back: result = append(result, node.Val). Calling append alone would discard the new element.
    • The loop bound is fixed. i < levelSize uses the number saved before the loop. Writing i < len(queue) would compare against a length that changes as nodes leave and children arrive.
    • []int{} versus nil. The function returns an empty, non-nil slice for an empty tree. Printed, it looks like [], and its len is 0.

    Complexity

    Time: O(n) for a tree of n nodes. Each node is added to the queue once and removed once, and each removal does a constant amount of work.

    Space: O(n) in the worst case. The queue holds at most about two levels at a time, and a complete tree has roughly n / 2 nodes in its last level. The result holds one value per level, which is never more than n.

    Edge cases and common mistakes

    • Empty tree. rightSideView(nil) returns an empty slice, with length 0. Without the early return, the queue would start with a nil pointer and node.Val would panic.
    • Single node. A tree with only the value 7 gives [7].
    • Only left children. A chain 1, 2, 3 going left each time gives [1 2 3], since each node is alone on its level. Following only right children would return just [1].
    • Left subtree deeper than the right. With root 1, children 2 and 3, 2 having children 4 and 6, and 4 having a child 8, the answer is [1 3 6 8]. The 6 and the 8 come from the left subtree.
    • Repeated values. A root 4 with two children that are both 4 gives [4 4]. The result lists one value per level, so equal values on different levels still appear separately.
    • Taking only right children. On the second example tree this gives [1 3], missing 4.
    • Forgetting to save the level size. The count must be read before the inner loop starts, or the loop mixes the current level with the next one.

    Testing

    • Root 1, children 2 and 3, grandchildren 5 (under 2) and 4 (under 3) gives [1 3 4].
    • Root 1, children 2 and 3, grandchild 4 under 2 gives [1 3 4].
    • nil gives [].
    • A single node 7 gives [7].
    • A left-only chain 1, 2, 3 gives [1 2 3].
    Keep going with Go500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free