Uber | New Grad SDE Phone Screen USA | First Unique Number
Summary
I interviewed for a New Grad Software Engineer position at Uber via a phone screen, where I was asked to implement a First Unique Number‑style problem. I ultimately received a rejection.
Full Experience
Uber | New Grad SDE Phone Screen USA | First Unique Number
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.
Introduction
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 once
They also provided this example:
post(1)
post(3)
getEarliestSingleVisit() # returns 1
post(1)
post(5)
getEarliestSingleVisit() # returns 3
Clarifying Questions
I 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.
Initial Complexity Discussion
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.
Pseudocode and Example Walkthrough
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:
- Maintain a queue representing IDs in the order they were first posted.
- Maintain a set for IDs that had been posted exactly once.
- Maintain another set for IDs that had been posted multiple times.
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, 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.
Code Implementation
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.
Follow‑Up
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.
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.
Interviewer Dynamic
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?"
Closing Questions
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.
Result and Takeaways
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:
- Clarify early whether the interviewer expects one problem with follow‑ups or multiple problems.
- Ask explicitly what target complexity they're ultimately looking for.
- Move from pseudocode to implementation faster once the general approach is established.
- Build deliberate time checks into the interview rather than relying on myself to notice the clock.
- When an interviewer suggests an optimization, step back and analyze the amortized complexity before dismissing it based on the apparent worst case of an individual operation.
- If I sense the interviewer is dissatisfied, directly ask something like: "It sounds like you may be looking for a stronger complexity here. Should I pause implementation and think about optimizing this further?"
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?
Interview Questions (1)
First Unique Number (Earliest Single Visit)
Implement two functions:
post(id) # Record a visit of the given ID
getEarliestSingleVisit() # Return the earliest ID that has been posted exactly once, or -1 if none exists
Example:
post(1)
post(3)
getEarliestSingleVisit() # returns 1
post(1)
post(5)
getEarliestSingleVisit() # returns 3
Constraints:
- IDs are integers up to around 10^6.
- Assume all data fits in memory.
- Aim for O(1) average time per operation, or O(1) amortized for
getEarliestSingleVisit.