Hacker News new | ask | show | jobs
by Jasper_ 474 days ago
Has anybody ever figured out what "invert a binary tree" means? That came from Max Howell, and nobody else seems to have ever received that question.

The best anyone can figure out is that it's reversing the left and right branches, which seems like it's ten lines of code, at most?

5 comments

leetcode seems to agree with your definition [0]. the meme isn't to say that inverting a binary tree is particularly difficult - anyone familiar with coding challenges and trees could trivially produce a solution. the meme is more pointing out how ludicrous it is that senior/staff/principal interviews can hinge on these types of problems, despite the engineer proving their proficiency by doing something like running DOOM in typescript types or writing homebrew [1].

[0] https://leetcode.com/problems/invert-binary-tree/description...

[1] https://x.com/mxcl/status/608682016205344768

I think those challenges (especially leetcode) are heavily misused.

When my team conducts technical interviews, we are asking for a couple simple programming solutions - but we're asking because we want to hear the candidate talk through it and see what their problem solving process is like.

If you aren't evaluating based on conditions like those, I don't really see the value of coding questions.

I agree with this. I got to experience both sides when I interviewed at FB/Meta. I practiced the leetcode and Cracking the Code Interview stuff of course and one of my interviewers asked something like that. I guess it was insulting and pointless but whatever - I just did it.

Another interviewer asked a much more interesting question: you are writing an IM client. How do you build the client-server communication?

That was a great conversation I enjoyed on its own without regard for the interview. Asking questions: do we have online/offline status? (yes) What are the target devices? (mobile).

IIRC I said I'd want to optimize for bandwidth and latency. Cellular networks can be spotty at times and stall out in really annoying ways. I'd design the protocol to use an efficient encoding with a pre-shared dictionary (the list of friends doesn't change that much after all and lots of the same words/emoji are used frequently). I also said I'd make a flexible format that would let things like online/offline status or you have a new message from X ride along with an actual message in the current conversation and explore options like QUIC or other UDP-based eventually-consistent options given how a cellular dead band can put you in TCP retransmit jail for minutes at times.

For closure I was offered a position but went to a different company.

> If you aren't evaluating based on conditions like those, I don't really see the value of coding questions.

The way I think about it, you're really trying to evaluate a candidate on about 10 different metrics all at once. Metrics like programming skill (writing & debugging), communication skills (listening and explaining), capacity to learn, domain knowledge (eg if you're hiring a react dev, do they know HTML & react?), likeability, and so on.

A good interview gives the candidate the chance to show their worth in all of those different areas. But time is limited - so you want some different challenges which will show many capabilities at once.

Asking a candidate to talk through how they'd solve a "leetcode problem" sort of does that - you can see their CS knowledge and their communication skills. But if thats all you ask, you end up overemphasising the candidate's CS knowledge. Most people aren't very good at thinking and talking at the same time. And you don't learn about other stuff. How good are they at debugging? At reading code? Do they have domain knowledge? Can they talk to clients? Are they good at design? Its also quite easy for the interviewer to be distracted by the question of whether or not the candidate solved the problem you gave them. - Which isn't really what anyone is there for.

As part of a larger interview, and especially for systems engineering roles, I think they're still fine questions to ask. But if thats the entire job interview, its a bad interview - because it won't let you evaluate a candidate properly. Especially in product roles where CS knowledge isn't very relevant anyway.

Our technical questions typically stay within the realm of the position we are hiring for, so technical usually revolves around “would you use X or Y in this scenario? Why?”

Understanding how someone thinks is more core to evaluating candidates, so questions like “let’s say you own a window washing company and you’ve been hired to wash every window on every skyscraper in New York City - how do you do it?” provide a much better insight into how someone goes about approaching a challenge.

A coworker has a simple diagram they use outlining a tech stack: backend, cache, frontend, and they give a brief overview of the “application.” Then they explain that there’s a big report that “customer says X isn’t working - how would approach fixing this?” It’s less technical on details and more about again how they would approach finding the issue.

This is absolutely the way. My interviews are conversations with someone that I want to work closely with, and while leet code might be an interesting lunch conversation it’s not going to be part of any of our day to day work (c/c++/swift/obj-c)
I think brew's author point holds even if you replace "invert binary tree" with any other LC problem.

In terms of the problem itself, a binary tree can be expressed something like:

    type Node<T> = { value: T, left?: Node<T>, right?: Node<T> }
Given a root, you can invert it recursively with some code like this:

    function invertTree(root) {
      if (!root) return null;

      // Swap!
      const tmp = root.left;
      root.left = invertTree(root.right);
      root.right = invertTree(tmp);

      return root;
    };
Or using an explicit stack:

    function invertTree(root) {
      const stack = [root];
      while (stack.length > 0) {
        const node = stack.pop(); if (!node) continue;

        // Swap!
        const tmp = node.right;
        node.right = node.left;
        node.left = tmp;

        stack.push(node.left);
        stack.push(node.right);
      }
      return root;
    }
I think without prep would be harder to come up with the non-recursive version.
Maybe the catch was in saying that left right labels are arbitrary, could be called node1 and node2 as well, inverting is not necessary per se, just visit it in node2, node1 order if needs to be flipped - ie. no physical rearrangement is necessary.
Also the best answer to "how do you reverse an array". You don't. You just read it in the opposite order. Especially in any iterator-based language it should be trivial.

In a pure ASCII world, this doubles as "how do you reverse a string". In a Unicode world, the answer to "how do you reverse a string" is "you should never want to do that".

Right, but sometimes you actually do have to reverse the array.
I can't remember the last time I reversed an array. Honestly it's at least a code smell. Why can't your code just read it in the other direction? Or have it in the correct order in the first place (e.g., sort it correctly instead of sorting it backwards and then reversing it). It's not that hard, even in a C-style for loop language.
Because usually the code to handle it is not mine and it expects to go through the list in forward order. Nobody makes APIs that take a list of, idk, files to delete and lets you pass in a parameter that is “please actually run your for loop over this in reverse”. They expect you to flip your array before you hand it in.
That's what it means, and people use it as an example not because it's like, some sort of super difficult unreasonable challenge, but because it's completely unrelated to the work you'd be doing on the job like 99.99% of the time. It's like interviewing for a line cook and asking them to make a spatula.
Depends on how you look at it, I guess. A binary tree has a couple of properties. Usually there is some ordering on the type. Something like: the element on the left is smaller than the element on the right. (e_L < e_R). Invert would be than turning the ordering into e_R > e_L. I guess this is the left and right branches exchange answer.

If you see a binary tree T e as some kind of function, it can test whether an element exists, a typical set operation. So f : e -> {0,1}, where (e,1) means the element is in the binary tree. (e,0) means it is not in the binary tree. All those (e,0) creates some sort of complement tree, which might also be seen as inverting it.

What would be really weird is seeing it as a directed acyclic graph and invert the direction of every edge.