LeetCode - Populating Next Right Pointers in Each Node I


Given a full binary tree, populate the nextRight pointers in each node.
In a full binary tree, each node other than the leaves has two children.


Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL. Initially, all next pointers are set to NULL.

  • You may only use constant extra space.
  • You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two children).
X. BFS
After analysis the example, you can find two rules:
  • root.left.next = root.right
  • root.right.next = root.next.left
Using a boolean type to check whether the curr.left is the left most node or not
  • if yes, using a temporary node to track for the left node of root.
  • if not, continue
After go through the two rules, we should check whether the current node is the right most node of current level. If not, we can just curr = curr.next to continue, if yes, we should jump to the next level (Using the temporary and boolean type)

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public void connect1(TreeLinkNode root) {
   TreeLinkNode curr = root;
   TreeLinkNode node = null;
   boolean mostLeftNode = true;
   while (curr != null) {
       if (curr.left != null) {
           if (mostLeftNode) {
               node = curr.left; // don't need this
               mostLeftNode = false;
           }
           curr.left.next = curr.right;
       }
       if (curr.right != null && curr.next != null) {
           curr.right.next = curr.next.left;
       }
       if (null == curr.next && curr.left != null) {
           curr = node; // curr = curr.left
           mostLeftNode = true;
       } else {
           curr = curr.next;
       }
   }
}
Improvement: Instead of using a temporary node and boolean variable, we can just use one node to check for the conditions.
public void connect(TreeLinkNode root) { TreeLinkNode n = root; while(n != null && n.left != null) { TreeLinkNode pre = null; for(TreeLinkNode p = n; p != null; p = p.next) { if(pre != null) pre.next = p.left; p.left.next = p.right; pre = p.right; } n = n.left; } }
http://www.programcreek.com/2014/05/leetcode-populating-next-right-pointers-in-each-node-java/
public void connect(TreeLinkNode root) {
    if(root == null) 
        return;
 
    TreeLinkNode lastHead = root;//prevous level's head 
    TreeLinkNode lastCurrent = null;//previous level's pointer
    TreeLinkNode currentHead = null;//currnet level's head 
    TreeLinkNode current = null;//current level's pointer
 
    while(lastHead!=null){
        lastCurrent = lastHead;
 
        while(lastCurrent!=null){
            if(currentHead == null){
                currentHead = lastCurrent.left;
                current = lastCurrent.left;
            }else{
                current.next = lastCurrent.left;
                current = current.next;
            }
 
            if(currentHead != null){
                current.next = lastCurrent.right;
                current = current.next;
            }
 
            lastCurrent = lastCurrent.next;
        }
 
        //update last head
        lastHead = currentHead;
        currentHead = null;
    }
 
}
X. BFS, but using extra queue
树的广度优先搜索题。记录下每一层的节点总个数,然后根据广度优先搜索的原则进行遍历,将非null节点都加入到队列中,对于同一层中的节点,将其next指向队列中的下一个节点即可。
    public void connect(TreeLinkNode root) {
        if (root == null)
            return;
        LinkedList<TreeLinkNode> nodes = new LinkedList<TreeLinkNode>();
        nodes.add(root);
        int numOfLevelTotal = 1;
        while (!nodes.isEmpty()) {
            TreeLinkNode treeLinkNode = nodes.poll();
            numOfLevelTotal--;
            if (treeLinkNode.left != null) {
                nodes.add(treeLinkNode.left);
            }
            if (treeLinkNode.right != null) {
                nodes.add(treeLinkNode.right);
            }
            if (numOfLevelTotal > 0) {
                treeLinkNode.next = nodes.getFirst();
            } else {
                numOfLevelTotal = nodes.size();
            }
        }
    }
Use extra queue - a little different than previous one.
public void connect(TreeLinkNode root) {
    if (root == null) {
        return;
    }
    
    Queue<TreeLinkNode> queue = new LinkedList<TreeLinkNode>();
    queue.offer(root);
    
    while (!queue.isEmpty()) {
        int size = queue.size();
        
        for (int i = 0; i < size; i++) {
            TreeLinkNode node = queue.poll();
            
            if (i == size - 1) {
                node.next = null;
            } else {
                node.next = queue.peek();
            }
            
            if (node.left != null) {
                queue.offer(node.left);
            }
            if (node.right != null) {
                queue.offer(node.right);
            }
        }
    }
}
X. Recursive version: 
         1 -> NULL
       /  \
      2 -> 3 -> NULL
     / \  / \
    4->5->6->7 -> NULL
这题主要的难点在于处理节点5的next,因为5的next要指向它的sibling,但在5这层是没法获取到3的引用
解决方法是:由于2所在那层已经建立好next链接,所以只需由2即可得到3的引用,继而得到3的left节点
 1 public void connect(TreeLinkNode root) {
 4         if(root == null){
 5             return;
 6         }
 7         if(root.left != null){
 8             root.left.next = root.right;
 9         }
10         if(root.right != null){
11             root.right.next = (root.next != null) ? root.next.left : null;
12         }
13         
14         connect(root.left);
15         connect(root.right);
16     }
    public void connect(TreeLinkNode root) {
        if (root == null)
            return ;
        if (root.left != null){
           root.left.next = root.right;
        }
        if (root.right != null && root.next!= null)
           root.right.next = root.next.left;
        connect(root.left);
        connect(root.right);
    }

Given the following perfect binary tree,
        1
      /  \
     2    3
    / \  / \
   4  5  6  7
After calling your function, the tree should look like:
        1 -> NULL
      /  \
     2 -> 3 -> NULL
    / \  / \
   4->5->6->7 -> NULL
My first thought is to use Breadth-First Search (BFS). After all, we are connecting the nextRight node level-by-level, it is only natural to apply BFS to this problem. I mentioned this approach to the interviewer, but he was not too satisfied with it.
BFS requires memory space to store Nodes into a queue. Can we do better without extra space?
The first key to solving this problem is we have the nextRight pointer. Assume that the nextRight pointers are already populated for this level. How can we populate the next level? Easy… just populate by iterating all nodes on this level. Another key to this problem is you have to populate the next level before you go down to the next level, because once you go down, you have no parent pointer.
void connect(Node* p) {
  if (p == NULL)
    return;
  if (p->leftChild == NULL || p->rightChild == NULL)
    return;
  Node* rightSibling;
  Node* p1 = p;
  while (p1) {
    if (p1->nextRight)
      rightSibling = p1->nextRight->leftChild;
    else
      rightSibling = NULL;
    p1->leftChild->nextRight = p1->rightChild;
    p1->rightChild->nextRight = rightSibling;
    p1 = p1->nextRight;
  }
  connect(p->leftChild);
}
Added alternative solution
Before we passed the leftChild and rightChild to the recursion function itself, we connect the rightChild’s nextRight to the current node’s nextRight’s leftChild. In order for this to work, the current node’s nextRight pointer must be populated
void connect(Node* p) {
  if (!p) return;
  if (p->leftChild)
  p->leftChild->nextRight = p->rightChild;
  if (p->rightChild)
    p->rightChild->nextRight = (p->nextRight) ?
                               p->nextRight->leftChild :
                               NULL;
  connect(p->leftChild);
  connect(p->rightChild);
}
Iterative Version:
The order of visits of tree node is the same as LeetCode - Binary Tree Level Order Traversal. But now we do not need to maintain a queue, since the reference  next gives exactly the next node in the same level. So we can work on each level, and visit each node in a level in sequence.
public void connect(TreeLinkNode root) {
        if (root == null)   // Empty tree
            return;
        TreeLinkNode headOfNextLevel = root;
        // Between levels
        while(headOfNextLevel != null) {
            // Initialize tailOfNextLevel and current, and update headOfNextLevel to null
            TreeLinkNode tailOfNextLevel = null, current = headOfNextLevel;
            headOfNextLevel = null;
            // Within a level
            while(current != null) {
                // Update headOfNextLevel if we find the first node in the next level
                if (headOfNextLevel == null && current.left != null)
                    headOfNextLevel = current.left;
                // Not a leaf; link its children
                if (current.left != null)
                    current.left.next = current.right;
                // Link the currently last node in the next level to the left subtree of current node
                if (tailOfNextLevel != null)
                    tailOfNextLevel.next = current.left;
                // Update tailOfNextLevel to the right subtree, and
                // move to the next node in the same level
                tailOfNextLevel = current.right;
                current = current.next;
            }
        }
    }

Related: LeetCode - Populating Next Right Pointers in Each Node I
Read full article from LeetCode - Populating Next Right Pointers in Each Node | Darren's Blog

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts