Hi everyone, I wanted to share my recent phone screen experience for an Uber New Grad Software Engineer position. I was asked one question that was very similar to LeetCode's First Unique Number.
I'll break the interview down by each phase of the call. I also want to share some of the interpersonal aspects of the interview because, honestly, that was one of the stranger parts of the experience for me.
The interviewer joined the call along with a junior engineer who was shadowing the interview. We briefly introduced ourselves.
The primary interviewer was initially upbeat and friendly. They explained that they wanted the interview to focus primarily on problem solving and bouncing ideas back and forth, rather than worrying too much about the code itself. They also mentioned that we could potentially end the call early if I finished the problem early.
They then gave me two functions to implement in a Jupyter Notebook:
post(id) # Post an ID
getEarliestSingleVisit()
# Return the earliest ID that has been posted exactly onceThey also provided this example:
post(1)
post(3)
getEarliestSingleVisit() # returns 1
post(1)
post(5)
getEarliestSingleVisit() # returns 3I started by asking clarifying questions about the expected behavior of each function and wrote my notes as comments above my implementation.
One thing I missed at this stage was asking what should happen if every ID had already been posted more than once. That edge case came up later during implementation.
I also asked about the upper bound on the IDs. The interviewer said the maximum ID would be around 10^6 and that I could assume everything would fit into memory, so space complexity was not a major concern.
I then talked through the complexity I thought would make sense.
Since memory was not a major constraint, I said we should probably aim for O(n) or better overall. I mentioned that post() could potentially be O(1) if we maintained the right data structures, while getEarliestSingleVisit() could initially be O(n) and then potentially be optimized.
The interviewer said they were okay with starting from that approach.
I started walking through their example before coding.
My first thought was to store posts as (timestamp, id) tuples so I could track which unique ID appeared earliest. The interviewer pointed out that a timestamp was unnecessary.
I reconsidered the problem and realized the ordering of a queue could already represent arrival order.
My approach became:
Because hash-set insertion, lookup, and removal are typically O(1) on average, this seemed like a reasonable starting point.
I wrote the pseudocode as comments and manually walked through the provided test case.
Around this point, I noticed a pretty clear change in the atmosphere of the interview. The primary interviewer, who had initially been friendly and encouraging, started to come across as increasingly confused or irritated with my reasoning. The junior engineer who was shadowing also seemed fairly unfriendly or disengaged.
Obviously, tone is subjective, so I can't know what either person was actually thinking. But from my side of the call, the change was noticeable enough that I started wondering whether I had made some major mistake that nobody was explicitly pointing out.
I tried not to let that affect me and continued working through the problem.
After walking through the example, I asked whether they were okay with me moving on to implementation. They said yes.
While coding, I explained what each part of the implementation was doing.
Partway through, I realized I had not handled the case where there were no IDs that had been posted exactly once. I asked what they wanted returned in that situation, and they said -1.
Once I finished coding, I began manually walking through another test case.
The interviewer interrupted and asked, in a noticeably annoyed tone:
"Don't you want to run your code?"
That caught me off guard because up until then I had understood the interview to emphasize talking through the solution and problem-solving collaboratively. I stopped the walkthrough and ran the code.
At this point, I checked the time and realized there were only about seven minutes left in the coding portion of the interview.
The code ran, but I initially saw an unexpected output. I thought some state from a previous execution might still exist in the Jupyter kernel and asked whether we should reset it. The interviewer said that would not help.
I then started debugging by printing the queue, which appeared correct.
Eventually, I realized the issue was simply that I had forgotten to rerun one of the cells above my test cell. Once I executed it, the implementation worked correctly.
There was then another small Jupyter-specific issue. The test cell contained:
post(1)
post(3)
getEarliestSingleVisit()
post(1)
post(5)
getEarliestSingleVisit()Only the result of the final expression was being displayed.
The interviewer wanted to see both outputs. I realized this was normal Jupyter behavior, so I temporarily printed the results instead, which showed both expected values.
Once the code was working, there were about five minutes remaining.
The interviewer asked me again about the time complexity. I explained it, but they still seemed dissatisfied with the solution.
This was also somewhat confusing because I had discussed the complexity of my approach several times already, including before I started coding, and the interviewer had previously indicated that they were okay with the approach.
They then asked how I would make getEarliestSingleVisit() run in O(1).
I thought aloud about a few possibilities, including shifting more work into post(), potentially using a heap, or using something like an ordered dictionary to maintain IDs in insertion order while also tracking their frequencies.
The interviewer did not seem satisfied with those answers.
They then suggested that when IDs become duplicated, I could prune duplicated IDs from the queue so that the front always represents the earliest ID that has only appeared once.
At the time, I wasn't immediately convinced because I was thinking about the possibility of repeatedly walking through the queue and worried that this could become expensive. In retrospect, this is where I should have stopped and analyzed the amortized complexity: if each ID can only be removed from the queue once, the total pruning work across all calls can still be linear, making each operation O(1) amortized.
I didn't fully work through that observation before time ran out.
The interviewer then said something along the lines of:
"Okay, I guess I'll submit what code you have now."
We moved on to closing questions shortly afterward.
This part of the interview left me pretty confused. At the beginning, I had been explicitly told that the emphasis was on problem solving and bouncing ideas around rather than worrying too much about the code. I had therefore deliberately spent time communicating my reasoning, checking assumptions, and walking through examples. Later in the interview, however, I got the strong impression that I was being judged for not reaching the optimized implementation quickly enough.
Maybe I simply misread what the interviewer wanted, but I found the mismatch between the expectations communicated at the beginning and the tone later in the interview difficult to navigate.
I also want to mention this separately because it stood out to me almost as much as the technical problem.
The primary interviewer went from being very upbeat at the beginning to sounding increasingly irritated as the interview progressed. The junior engineer shadowing the interview also came across as unfriendly during much of the interaction.
I recognize that I'm describing my perception of their tone, and interviews are stressful enough that it's possible to misread people. But I found the dynamic unusual because I was actively trying to engage with the interviewer in the collaborative way they had specifically requested.
What particularly struck me was that there was a junior engineer shadowing the interview, presumably in part to learn how interviews are conducted. In my opinion, showing visible frustration toward a candidate who is thinking aloud, asking questions, and attempting to work through a solution isn't a great example to set for someone learning how to interview candidates.
Technical interviews are obviously evaluative, and I don't expect interviewers to give away answers or reassure candidates constantly. But I do think there's a difference between challenging someone's reasoning and creating an atmosphere where the candidate feels that the interviewer is irritated with them for not seeing the intended solution quickly enough.
That aspect of the interview probably affected my performance as well. Once I noticed the change in tone, part of my attention shifted from solving the problem to wondering, "What am I doing wrong that is making them react this way?"
I asked about some of the engineering challenges they were working on at Uber, and the interviewer gave a fairly detailed answer.
Interestingly, the interviewer was much more conversational during this part, although the overall vibe was noticeably less upbeat than it had been at the beginning of the call.
I also asked whether they had any feedback for me. They said they did not.
We ended the call and they said I would hear back from the recruiting team.
I received a rejection email from the recruiter two days later.
I'm disappointed with the result, and I still think the interviewer dynamic was strange, but there are also several things within my control that I would do differently next time:
One challenge I have is that I can get tunnel vision once I'm deep into solving a problem and lose track of how much interview time has passed.
For people who have done a lot of technical interviews: how do you build time checks into your process without constantly distracting yourself from solving the problem?
Also curious whether others have experienced interviews where the tone of the interviewer changed dramatically partway through. How do you keep that from throwing you off when you're already trying to solve the problem under time pressure?