I completed kevincline's answer to include a tree class and also made some minor changes for convenience. Please note that naked pointers are not a good practice and are only used for the sake of this example.
Here is the complete, compileable code:
#include <iostream>
#include <map>
#include <vector>
class Tree {
public:
explicit Tree(int value) : _root(NULL), _left(NULL), _right(NULL), _sibling(NULL), _nodeValue(value) {}
~Tree() { if (_left) delete _left; if (_right) delete _right; }
Tree* root() const { return _root; }
Tree* left_subtree() const { return _left; }
Tree* right_subtree() const { return _right; }
Tree* sibling() const { return _sibling; }
int value() const { return _nodeValue; }
Tree* setLeft(Tree* t) { t->_root = this; return _left = t; }
Tree* setRight(Tree* t) { t->_root = this; return _right = t; }
void connect(Tree* s) { _sibling = s; }
private:
Tree* _root;
Tree* _left;
Tree* _right;
Tree* _sibling;
int _nodeValue;
};
typedef std::map<int, std::vector<Tree*> > nodes_by_level;
void join_siblings(int level, Tree* t, nodes_by_level& nodes) {
if (!t) return;
nodes[level].push_back(t);
join_siblings(level + 1, t->left_subtree(), nodes);
join_siblings(level + 1, t->right_subtree(), nodes);
}
nodes_by_level join_siblings(Tree& t) {
nodes_by_level nodes;
join_siblings(0, &t, nodes);
return nodes;
}
void printSiblings(Tree* t) {
if (!t) return;
if (t->sibling()) std::cout << "The sibling of " << t->value() << " is " << t->sibling()->value() << std::endl;
printSiblings(t->left_subtree());
printSiblings(t->right_subtree());
}
int main() {
Tree t(1);
Tree* two = t.setLeft(new Tree(2));
Tree* three = t.setRight(new Tree(3));
Tree* four = two->setLeft(new Tree(4));
two->setRight(new Tree(5));
Tree* six = three->setRight(new Tree(6));
four->setLeft(new Tree(7));
six->setRight(new Tree(8));
nodes_by_level nl = join_siblings(t);
std::cout << "Connected nodes: \n";
for (nodes_by_level::iterator it = nl.begin();
it != nl.end();
++it) {
std::vector<Tree*>& v = it->second;
for (size_t i = 0; i < v.size(); ++i) {
if (i < v.size() - 1) v[i]->connect(v[i+1]);
}
}
printSiblings(&t);
return 0;
}
Output is:
Connected nodes:
The sibling of 2 is 3
The sibling of 4 is 5
The sibling of 7 is 8
The sibling of 5 is 6
In total, it is 73 lines (including the empty lines as well). In an interview, you don't need to implement the code for the tree class and to build the tree itself, and to display the siblings like this. What they are interested in is the 14 lines of code that kevincline gave you as an answer.
Since this site is about professional advice, here is mine. Don't blame the failure on external factors. Here, you are trying to prove that the question was unreasonably hard, but it wasn't. You failed, but don't be offended. Look at it as an opportunity to improve yourself. Imagine if you didn't fail this interview and later screwed up something in production. Now you know an area where you can improve. That's great, take that chance. Next time, you can be much more confident in a similar interview.