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;
}
Nice and obvious. Thank you, Xiangyi.
ReplyDeleteYour solution is O(n^2). It could be done in linear time.
ReplyDeleteHow? Can you explain the solution?
DeleteYou 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.
DeleteI 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)
DeleteAfter swap, still need to push it to the queue....
DeleteThis comment has been removed by the author.
ReplyDeleteThe basic idea is to return a non-zero preorder deque for every node
DeletevectorsinkZeroBinaryTree(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;
}