Sunday, July 13, 2014

Sink Zero -- Facebook

Question:

Sink zero in Binary tree. Swap '0' value node with non-zero value node and its descendants so that no node with value '0' could be parent of node with non-zero.

Example:

Answer:
#include <stdio.h>
#include <string>
#include <vector>
#include <iostream>
#include <sstream>

using namespace std;

struct BTNode{
int val;
BTNode *left;
BTNode *right;
BTNode(int v): val(v),left(NULL),right(NULL){}
};

void postorder0(BTNode *);

void printTree(BTNode *root,int level){
   if(!root) return;

   printTree(root->left, level-1);

   for(int i=0; i<level; i++) {
     cout << "  ";
   }
   cout << root->val << endl;
 
   printTree(root->right, level-1);
   return;
}

void sinkZero(BTNode *root){
postorder0(root);
}

void preorder0 (BTNode *root){
if(!root) return;

if(root->val == 0){
if(root->left && root->left -> val!=0){
swap(root->val, root-> left->val);
preorder0(root->left);
}
else if(root->right && root->right->val != 0){
swap(root->val, root-> right->val);
   preorder0(root->right);
}
}
return;
}

void postorder0 (BTNode *root){
if(!root) return;

postorder0(root->left);
postorder0(root->right);

if(root->val == 0){
if(root->left && root->left->val!=0  || root->right && root->right->val!= 0){
preorder0(root);
}
}
return;
}

int main(){
BTNode *root = new BTNode (0);
root->left = new BTNode (0);
root->right = new BTNode (0);
root->left->left = new BTNode (0);
root->left->right = new BTNode (2);
root->right->left = new BTNode (3);
root->right->right = new BTNode (0);
root->left->left->left = new BTNode(0);
root->left->left->right = new BTNode(1);

printTree(root,4);
sinkZero(root);
cout<<endl<<"After sink zero elements down:"<<endl<<endl;
printTree(root,4);
getchar();
return 0;
}


8 comments:

  1. Nice and obvious. Thank you, Xiangyi.

    ReplyDelete
  2. Your solution is O(n^2). It could be done in linear time.

    ReplyDelete
    Replies
    1. How? Can you explain the solution?

      Delete
    2. You only need to scan a tree once. You need a double-ended queue to track information in tree traversal. I designed this question. If you were able to figure out the optimal solution, I would like to invite you to interview with us if you didn't do it before.

      Delete
    3. I guess: Still in post-order traverse the tree, if root->value !=0, push the node(pointer) to double-ended queue, should specify the direction: left child: left; right child: right.....I need to divide the left and right sub-tree for root node. Maybe keep an index in the queue....else if root->value ==0, then swap top node element in the left subtree ele in the queue or top node ele in right subtree in the queue 's value with 0. (Meaning swap 0 with most remote node's non-zero value in left or right sub-tree)

      Delete
    4. After swap, still need to push it to the queue....

      Delete
  3. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. The basic idea is to return a non-zero preorder deque for every node

      vectorsinkZeroBinaryTree(TreeNode *root){
      if (root==nullptr) return vector();

      vector leftNonZero=sinkZeroBinaryTree(root->left);
      vector rightNonZero=sinkZeroBinaryTree(root->right);
      vector nonZero=leftNonZero;
      nonZero.insert(nonZero.end(), rightNonZero.begin(),rightNonZero.end());

      if (root->val==0 && !nonZero.empty()) {
      TreeNode *swap=nonZero.back();
      root->val=swap->val;
      swap->val=0;
      nonZero.pop_back();
      nonZero.insert(nonZero.begin(), root);
      }
      else{
      nonZero.insert(nonZero.begin(), root);
      }
      return nonZero;
      }

      Delete