LogIn
I don't have account.

Uber SDE 2 Interview Experience (5 Rounds, Selected) - Complete DSA Questions with solution, System Design & Managerial Round

Vishnu Reddy

54 Views

Getting selected for an SDE 2 role at Uber Technologies, Inc. is not just about solving coding questions. it is about proving that you can think like an engineer who can build scalable systems, write maintainable code and handle real-world production challenges calmly.

I recently went through the complete interview process for the Uber SDE 2 interview and fortunately, I was selected after 5 rounds. The journey was intense, practical and very different from standard DSA-only interviews.

This was a remote interview process and the entire timeline took around 2–3 weeks. The process started with a CodeSignal assessment, followed by coding rounds, Low-Level Design, System Design and finally a managerial discussion.

If you are preparing for the Uber Software Engineer interview and looking article like Uber SDE 2 interview experience, Uber coding interview questions, Uber LLD interview, Uber system design interview or how to crack Uber interviews, this real experience will help you understand what actually happens.

One thing I learned very clearly:

Uber does not just test if you can code. They test:

  • how you think under pressure
  • how clearly you explain
  • how you design systems
  • how you handle ambiguity
  • how you respond when production problems happen

That is where senior interviews are truly decided. Let me walk you through every round in detail.

Interview Process Overview

There were a total of 5 rounds:

  • Round 1 – Online Assessment + Phone Screen
  • Round 2 – DSA Round (2 Problems)
  • Round 3 – Low-Level Design (Car Rental System)
  • Round 4 – System Design (Real-Time Notification System)
  • Round 5 – Managerial Round

The difficulty level was mostly medium, but the follow-up questions made the rounds much harder. The biggest lesson:

Strong communication + strong fundamentals = success at Uber

Round 1 – Online Assessment + Phone Screen

The interview process started with an online assessment on CodeSignal. It included three coding challenges and the difficulty level ranged from simple implementation-based questions to moderately complex DSA problems.

The goal here was not just solving quickly, but writing clean and correct solutions under time pressure. I made sure to complete all three questions carefully, paying extra attention to edge cases and test scenarios. That helped me clear the assessment and move to the next stage.

The next step was the phone screen and this round was much more focused on problem-solving approach rather than just final code. The interviewer picked a DSA problem based on string manipulation and edge-case handling, which at first looked easy, but turned out to be a strong test of precision.

Problem : Finding the Next Closest Palindrome

The interviewer asked:

You are given a number as a string. Find the next closest palindrome number that is strictly greater than the given number.

He gave a quick example:


Input: 123
Output: 131
  • 121 is a palindrome, but it is smaller than 123, so it cannot be the answer.
  • 131 is the next nearest palindrome greater than 123.

At first, this sounded like a straightforward problem, but the real difficulty was hidden in edge cases like:

  • odd-length numbers
  • even-length numbers
  • carry cases like 999 -> 1001
  • tricky inputs like 12932

This problem was more about careful implementation than difficult algorithms.

My First Thought During the Interview was the brute-force approach. I explained that we could simply increase the number by 1 and keep checking whether each new value is a palindrome. Something like:

123 -> 124 -> 125 -> 126 -> ... -> 131

This approach works and mentioning it first is completely fine in interviews because it shows your natural thought process. But I also told the interviewer that this would become too slow for very large numbers. If the input is something like 999999 or a very long numeric string, checking one by one would not be efficient. That naturally led to the optimized solution.

After that, I start thinking about some optimal Approach. The key observation is that a palindrome is formed by mirroring. The left half decides the right half. So instead of checking every next number, we can directly create the nearest palindrome by copying the left half to the right side.

For example:

123 -> 121

Now compare it with the original number. Since 121 < 123, it cannot be the answer. So the next step is to increment the middle digit and mirror again:

121 -> 131

Now 131 > 123, so this becomes the correct answer. This avoids unnecessary checking and gives an efficient solution in linear time. That is the approach interviewers usually expect.


public class NextPalindrome {

    public String nextPalindrome(String num) {
        int n = num.length();
        char[] arr = num.toCharArray();
        char[] palindrome = arr.clone();

        // Step 1: Mirror left half to right half
        for (int i = 0; i < n / 2; i++) {
            palindrome[n - i - 1] = palindrome[i];
        }
        String pal = new String(palindrome);
        // If mirrored palindrome is already greater
        if (pal.compareTo(num) > 0) {
            return pal;
        }
        // Step 2: Increment middle and handle carry
        int mid = (n - 1) / 2;
        while (mid >= 0 && palindrome[mid] == '9') {
            palindrome[mid] = '0';
            mid--;
        }
        // Case like 999 -> 1001
        if (mid < 0) {
            return "1" + "0".repeat(n - 1) + "1";
        }
        palindrome[mid]++;
        if (n % 2 == 0) {
            palindrome[n - mid - 1]++;
        }
        // Step 3: Mirror again
        for (int i = 0; i < n / 2; i++) {
            palindrome[n - i - 1] = palindrome[i];
        }
        return new String(palindrome);
    }
}

Follow-Up Question

The interviewer also asked:

What if the input is already a palindrome like 1221?

The important point here is that we still need the next greater palindrome, not the same one. So: 1221 -> 1331 not 1221 This small follow-up was actually important because it checked whether I fully understood the problem constraints.

Overall, Round 1 was a good reminder that simple-looking DSA problems can be the most dangerous ones if you ignore edge cases.

Round 2 – DSA Round

The second round was a pure DSA round, the expectation here was much higher. The interviewer was not just looking for a working solution. they wanted optimized thinking, clean explanation and confidence while handling constraints.

This round had two coding problems and both required quick reasoning. One of the most memorable ones was based on array manipulation and maintaining order, which sounds simple until I actually try solving it under interview pressure.

Problem 1: Rearrange Positive and Negative Numbers Alternately

The interviewer asked: Given an array containing both positive and negative numbers, rearrange them so that positive and negative numbers appear alternately while maintaining the relative order of elements.

He shared an example:


Input : [1, 2, 3, -4, -1, 4]
Output : [1, -4, 2, -1, 3, 4]

At first glance, it looks like a normal rearrangement problem, but there was one condition The relative order of positive and negative numbers must remain the same. that made it much harder. That means:

  • positives must stay in their original order
  • negatives must also stay in their original order

This condition removes many easy solutions. For example, simply swapping elements freely would break the ordering and make the answer incorrect. That is where the real challenge started.

The first approach that came to mind was the simple and safe one. I explained that we could create two separate arrays:

  • one for positive numbers
  • one for negative numbers

Then we could merge them alternately into the final result. This approach is easy to explain, easy to code and guarantees the relative order remains correct.

For the given example:


Positive -> [1, 2, 3, 4]
Negative -> [-4, -1]
Then merge: [1, -4, 2, -1, 3, 4]

The interviewer agreed that this works. But then came the expected follow-up: Can you do this with better space optimization? That is usually the signal that they are looking for the real interview solution. Now the goal changed. I needed to preserve order, alternate signs and avoid using extra arrays. That means solving it in-place.

The idea was to use: Two pointers with right rotation Instead of creating new arrays, we scan the original array and find elements that are out of place.

For example:

  • If a negative number appears where a positive should be or vice versa we mark that index.
  • Then we continue scanning until we find an element with the correct sign.
  • Instead of swapping directly, we perform a right rotation of that subarray.
  • This is important because simple swapping would destroy the original order.
  • Right rotation allows us to :
    • place the correct element in the required position.
    • preserve the relative order of all elements in between.

This is harder to code than the extra-space solution, but it shows much stronger problem-solving skills. That is exactly what the interviewer wanted.


import java.util.*;

public class RearrangeArray {
    public void rearrange(int[] arr) {
        int n = arr.length;
        int outOfPlace = -1;
        for (int index = 0; index < n; index++) {
            // If we already found an out-of-place element
            if (outOfPlace >= 0) {
                // Check if current element can fix it
                if ((arr[index] >= 0 && arr[outOfPlace] < 0) ||
                    (arr[index] < 0 && arr[outOfPlace] >= 0)) {
                    // Right rotate subarray
                    rightRotate(arr, outOfPlace, index);
                    // Update outOfPlace
                    if (index - outOfPlace >= 2)
                        outOfPlace += 2;
                    else
                        outOfPlace = -1;
                }
            }
            // Find the next out-of-place element
            if (outOfPlace == -1) {
                if (((arr[index] >= 0) && (index % 2 == 1)) ||
                    ((arr[index] < 0) && (index % 2 == 0))) {
                    outOfPlace = index;
                }
            }
        }
    }
    private void rightRotate(int[] arr, int start, int end) {
        int temp = arr[end];
        for (int i = end; i > start; i--) {
            arr[i] = arr[i - 1];
        }
        arr[start] = temp;
    }
}

This problem was not about advanced algorithms like graphs or DP. It was testing practical engineering thinking. Uber often asks these types of questions because real-world engineering problems are rarely about writing the longest algorithm. they are about handling constraints correctly.

Follow-Up Question

The interviewer also asked: Why not simply swap elements?

This was an important discussion. The answer is: Simple swapping breaks the relative order.

For example: If you swap directly, positives and negatives may no longer appear in the same sequence as the original input. Since the problem specifically asks to preserve order, rotation is preferred over swapping. That small detail made a big difference in the round.

Problem 2: First Non-Repeating Character in a Stream of Data

The second problem in this DSA round was based on stream processing and this one felt much closer to real-world backend engineering problems than a traditional textbook DSA question.

The interviewer asked: Characters are arriving one by one in a stream. After every new character arrives, return the first character that has appeared only once so far.

He explained it with an example:

Input Stream : a a b c
Output : a -1 b b
  • first a arrives -> a is the first non-repeating character
  • second a arrives -> now a repeats, so no unique character exists -> -1
  • b arrives -> now b becomes the first non-repeating character
  • c arrives -> b is still the first non-repeating character

At first, this sounds like a basic string problem, but the word stream changes everything. This means we are processing characters in real time and after every single input, we must produce an answer immediately. That makes efficiency very important.

My first Thought During the Interview was simple: After every new character arrives, scan the entire string from left to right and find the first non-repeating character. This would work logically.

For example, after each character, we could check frequencies and return the first unique one. But I immediately pointed out the problem. If the stream becomes large, scanning the full string after every new character becomes expensive. That would make the solution too slow and not scalable for real-time systems. The interviewer nodded, which usually means they want the optimized version.

After that, I think an optimal solution using Queue + HashMap. The idea is simple:

  • The HashMap stores the frequency of each character.
  • The Queue maintains the order in which characters arrived.

Whenever a new character comes:

  • increase its frequency in the map
  • push it into the queue

Now, if the front of the queue has frequency greater than 1, it means it is no longer unique. So we keep removing elements from the front until the front becomes a character with frequency 1. That front element becomes our answer.

If the queue becomes empty, it means no non-repeating character exists, so we return -1. This gives efficient real-time processing and avoids rescanning the full stream again and again.

That was the expected interview solution. This is much closer to production engineering than solving isolated static problems.


import java.util.*;

public class FirstNonRepeating {

    public void firstNonRepeating(String stream) {
        Map<Character, Integer> freq = new HashMap<>();
        Queue<Character> queue = new LinkedList<>();
        for (char ch : stream.toCharArray()) {
            // Update frequency
            freq.put(ch, freq.getOrDefault(ch, 0) + 1);
            // Add character to queue
            queue.offer(ch);
            // Remove repeating characters from front
            while (!queue.isEmpty() &&
                    freq.get(queue.peek()) > 1) {
                queue.poll();
            }
            // Print first non-repeating character
            if (queue.isEmpty()) {
                System.out.print("-1 ");
            } else {
                System.out.print(queue.peek() + " ");
            }
        }
    }
}

Follow-Up Question

The interviewer also asked: Why do we need both Queue and HashMap? Can't we solve it using only one?

This was an important follow-up. My answer is: The HashMap helps us track frequency quickly and the Queue helps us preserve insertion order.

If we use only a HashMap, we know which characters are repeating, but we do not know which unique character came first. If we use only a Queue, checking frequency becomes inefficient. Using both together gives the best balance of speed and correctness.

That explanation was important because interviewers often judge understanding more than code.

Round 3 – Low-Level Design Round

The third round was the Low-Level Design round and this felt very different from the DSA-heavy rounds before it. Here, the interviewer was not interested in algorithms or tricky edge cases. The focus was completely on object-oriented thinking, clean design and how well I could model a real-world system.

The problem given was: Design a Car Rental System.

At first, it sounds broad and that is exactly the challenge. In LLD rounds, interviewers want to see how you break down a real system into meaningful classes and responsibilities. Instead of jumping directly into code, I first discussed the major entities involved.

I started with the obvious ones: Cars, Users, Bookings, Inventory, Payment Services, Availability Tracking

I explained that every car should have details like vehicle number, type, model, pricing and availability status. Users should be able to search for available cars, make bookings and complete payments. Bookings should connect users with vehicles for a specific duration, while inventory should handle availability management. The interviewer was paying close attention to how responsibilities were divided.

For example, instead of putting everything inside one huge CarRentalSystem class, I separated concerns clearly.

  • The BookingService handled reservation logic.
  • The PaymentService handled payment flow.
  • The InventoryManager tracked available vehicles.
  • The User and Car classes were kept simple and focused on their own responsibilities.

This discussion became more important than the actual syntax. The interviewer specifically asked how the system would handle future changes.

For example:

  • What if pricing changes based on weekends?
  • What if luxury cars have a different pricing strategy?
  • What if new vehicle types like bikes or trucks need to be added later?

This is where design patterns helped. I explained that I would use the Strategy Pattern for pricing. Instead of hardcoding price calculation inside the car class, different pricing strategies could be created like:

  • DailyPricingStrategy
  • WeekendPricingStrategy
  • LuxuryCarPricingStrategy

This makes the system flexible because pricing logic can change without modifying existing classes. For vehicle creation, I suggested using the Factory Pattern.

If tomorrow we need to support SUVs, bikes, trucks or electric vehicles, the factory can handle object creation without affecting business logic. This showed extensibility, which the interviewer liked.

The main focus of the round was not writing perfect code. it was showing strong understanding of:

  • class responsibility
  • clean abstraction
  • extensibility
  • OOP principles
  • SOLID principles

Especially the Single Responsibility Principle and Open/Closed Principle came up during discussion. That was the biggest lesson from this round. Low-Level Design is not about writing classes quickly. It is about writing classes that can survive future changes without becoming a maintenance nightmare. That mindset matters much more than syntax.

Round 4 – System Design Round

The fourth round was the System Design round and this was probably the most discussion-heavy round of the entire interview process. Unlike DSA rounds where there is usually a clear solution path, here the interviewer wanted to understand how I think when designing large-scale systems.

The problem statement was: Design a real-time stock price notification system.

The use case was simple: If a user sets something like: Notify me if Tesla crosses $300 the system should monitor stock price updates and send a real-time alert when that condition is met.

At first, this sounds like a notification problem, but the real challenge is scale.

  • What happens when millions of users are tracking thousands of stocks at the same time?
  • What happens when stock prices are updating every second?
  • What happens when alerts fail, duplicate or arrive late?

That is where the real system design discussion begins.

I started by breaking the system into core components instead of jumping into architecture diagrams.

The first service was the Price Feed Service. This service is responsible for continuously receiving stock price updates from market data providers like exchanges or third-party APIs. Since prices can change every second, this layer must be highly reliable and capable of handling high-frequency updates.

Instead of directly sending these updates to downstream services, I introduced Apache Kafka for event streaming. Kafka acts as the buffer between producers and consumers. It helps decouple services, handle spikes in traffic and ensures that price updates are not lost if one downstream service becomes slow.

This was an important part of the design because real-time systems should never depend on direct synchronous communication for high-volume event streams.

Next came the Rule Evaluation Engine. This service consumes price updates from Kafka and checks whether any user-defined alert conditions are met.

For example:

  • Tesla crosses $300
  • Apple drops below $180
  • Nvidia increases by more than 5%

Instead of scanning all users every time, I explained that subscriptions should be indexed by stock symbol and threshold ranges so matching becomes faster. This reduces unnecessary computation and improves scalability significantly.

Once a condition is matched, the event moves to the Notification Service. This service handles sending alerts through multiple channels such as: push notifications, email, SMS, in-app notifications

I also discussed idempotency here because duplicate alerts are a real problem. For example, if Tesla crosses $300 and the same event gets processed twice, users should not receive duplicate notifications.

To solve this, I suggested using unique event IDs and storing notification status so duplicate processing can be avoided. The interviewer liked this part and immediately pushed further.

He asked: What if Kafka fails?

This is where interviews are often won. I explained that Kafka should be deployed as a replicated cluster with multiple brokers and replication factors greater than one. This ensures fault tolerance and prevents data loss if one broker goes down.

Consumers should also support replaying events using offsets so missed notifications can be recovered safely.

Then came another question: What if millions of users subscribe to one stock like Tesla?

This was clearly a scalability test. I explained that horizontal scaling becomes necessary. The Rule Engine should be partitioned by stock symbol and Kafka topics should also be partitioned to distribute load across multiple consumers.

Caching frequently accessed subscription rules and using distributed processing helps avoid bottlenecks.

Then came another question: What if duplicate alerts are sent?

Again, this was less about architecture and more about production reliability. I explained:

  • idempotent consumers
  • deduplication keys
  • persistent notification logs
  • retry-safe operations

This ensures users do not lose trust in the system because duplicate alerts can quickly make a product feel broken.

I also included a Retry Queue for failed notifications. Sometimes SMS gateways fail, email services timeout or push notifications are delayed.

Instead of losing those events, failed deliveries should move to a retry queue with exponential backoff so the system can recover gracefully without overwhelming downstream services.

Finally, I discussed Monitoring and Alerts. Metrics like:

  • notification success rate
  • Kafka consumer lag
  • retry queue size
  • duplicate alert rate
  • failed event count

should be tracked using monitoring tools like dashboards and alerting systems. Because in real production systems, observability is as important as architecture.

The biggest lesson from this round was simple: System Design interviews are rarely about drawing boxes. They are about how you respond when the interviewer starts attacking your design.

Questions like:

  • What breaks first?
  • What happens during failure?
  • How do you recover?

That is where strong candidates separate themselves. This round taught me that interviews are won less by the first design and more by how calmly you defend it under pressure.

Round 5 – Managerial Round

The final round was the Managerial round and honestly, this turned out to be one of the most important rounds in the entire Uber interview process. By the time you reach this stage, the company already has enough evidence that you can write code, solve DSA problems and design scalable systems. They have already tested your technical depth through coding rounds, Low-Level Design and System Design discussions.

Now they want to answer a different question: Can we trust this person to work with real teams, real deadlines and real production problems?

That is what this round is actually about. This round was not about syntax, algorithms or architecture diagrams. It was about mindset, ownership, communication and maturity as an engineer. The interviewer was trying to understand how I behave when things are not ideal when there is conflict in the team, when deadlines are tight, when production breaks or when priorities change unexpectedly.

The main areas they were evaluating were:

  • ownership mindset
  • collaboration style
  • leadership thinking
  • handling production incidents
  • decision-making under pressure
  • communication with cross-functional teams

The conversation felt much more like a discussion than an interview. It was less about right answers and more about how honestly and clearly I could explain my real experiences. Some of the questions were:

  • Tell me about a time you disagreed with your teammate or manager.
  • How do you prioritize tasks when deadlines are tight?
  • Describe a performance bottleneck you fixed.
  • If your feature fails in production during peak hours, what would you do first?

These questions may sound simple compared to coding rounds, but they are actually much harder because you cannot prepare them by memorizing solutions. You need real examples and real judgment.

For the disagreement question, the interviewer was not checking whether I had conflicts in the past. In fact, conflicts are normal in strong engineering teams. What they wanted to know was how I handled that disagreement.

  • Did I listen first before reacting?
  • Did I focus on solving the problem instead of proving myself right?
  • Did I use data, metrics and business impact to support my opinion?
  • Did I maintain trust and respect with the teammate after the disagreement?

I answered using a real example where there was disagreement about the implementation approach for a feature rollout. One side wanted a quick patch for faster delivery, while I believed the solution would create technical debt and production risks later. Instead of turning it into a personal argument, I collected performance data, discussed long-term maintenance costs and proposed a middle-ground solution that balanced delivery speed with stability.

That showed ownership and collaboration, which mattered much more than simply saying we resolved it. For the prioritization question, the interviewer wanted to understand whether I think like an engineer or like an owner.

There is a big difference.

An engineer may focus only on completing assigned tasks. An owner thinks about customer impact, business urgency, dependencies and team bandwidth.

I explained that when deadlines are tight, I first identify what directly affects customers or revenue, what can block other teams and what can safely be delayed. I also believe in communicating trade-offs early instead of silently struggling.

For example, if two high-priority tasks arrive together, pretending both can be completed perfectly is not leadership. Clearly discussing risks, timelines and priorities with stakeholders is much more valuable.

That is what interviewers want to hear. The production failure question was one of the most important.

The interviewer asked: If your feature fails in production during peak hours, what would you do first?

This question reveals a lot. A weak answer usually starts with: I would start debugging the code. But that is not the best first step. The first responsibility in production is not debugging. it is stabilization. I explained that my first priority would be reducing customer impact.

That means:

  • checking how severe the issue is
  • identifying whether rollback is needed
  • disabling risky feature flags if possible
  • informing stakeholders and support teams
  • making sure monitoring is active

Only after the system is stable should deep root cause investigation begin. This shows production maturity.

I also shared a real example where an API performance issue caused slow responses during high traffic. Instead of immediately trying risky fixes in production, we first reduced load by scaling resources temporarily, monitored failure rates and communicated updates to dependent teams. Once stability returned, we investigated the database bottleneck and optimized inefficient queries permanently.

That practical explanation created much stronger impact than a textbook answer. The performance bottleneck question was also important because it tested whether I understand optimization beyond theory.

I explained a case where repeated database calls inside a frequently used API created latency issues. By analyzing logs and query patterns, I found unnecessary repeated queries and poor indexing. We optimized the query structure, added proper caching where needed and improved the response time significantly.

The interviewer was more interested in how I identified the issue and collaborated during the fix than the exact technical details.

That taught me something valuable:

  • Managerial rounds are not about sounding perfect. They are about sounding real.

If your answers feel too polished or artificial, interviewers notice immediately. Authenticity wins here.

Real examples build trust because they show how you think under pressure, how you work with people and how you respond when things go wrong. That matters far more than textbook leadership definitions.

Final Result – Selected

Fortunately, I got selected. But when I look back honestly, I do not think selection happened because I solved every problem perfectly.

There were moments where I could have given better answers. There were follow-up questions that forced me to think harder. There were places where I had to pause and structure my thoughts carefully.

What made the difference was not perfection. It was:

  • structured thinking
  • clear communication
  • strong understanding of real-world systems
  • calm handling of follow-up questions
  • practical examples from actual experience
  • confidence without arrogance

That is something many candidates misunderstand during interview preparation. They spend months trying to memorize perfect answers, but interviews are rarely about perfection. Interviewers are trying to understand how you think when things become uncertain.

  • Can you stay calm?
  • Can you explain your decisions clearly?
  • Can you handle pushback without panic?
  • Can you take ownership when something breaks?

That is what gets remembered. The biggest lesson from the entire Uber interview experience was simple:

You do not need to be perfect. You need to be reliable.

Because companies are not hiring someone to solve one interview problem. They are hiring someone they can trust with real systems, real customers and real production challenges. That mindset changed everything for me.

Responses (0)

Write a response

CommentHide Comments

No Comments yet.