DoorDash Software Engineer Interview Experience — Rejected After a Dasher Pay Coding Screen With No Starter Code

DoorDash·Software Engineer·Mar 2026
Technical ScreenRejectedmedium

I got a question that's pretty common on the forum, a combination of a Bootstrap-style problem and DoorDash Pay. The interviewer didn't give me any starter code, just the description below.

He said to assume I'm a downstream service and the data comes from upstream. The answer I wrote turned out to be correct, it's just that the data was test cases, not data mocked from an upstream interface. A few days later I got rejected and I have no idea where I went wrong. Anyone have any pointers? The question and the code I was given at the time were roughly like this:

Dasher Naive Pay

Background: as a Dasher, your pay is calculated based on "active time." The system logs your actions on different orders as events.

Rules and definitions:

  • Base rate: pay is calculated per minute, at a base rate of $0.3/min.
  • Active order: an order is considered active from when you accept it (ACCEPT) until you complete the delivery (FULFILL).
  • Multiplicity (stacked pay): in the Part 1 logic, pay stacks linearly. If you're handling multiple active orders at the same time, the pay for each minute = number of active orders x base rate. Example: if you have two active orders at the same time for 10 minutes, the pay for that stretch is 2 x 0.3 x 10 = 6.0.

Input: events, a list of events, each containing:

  • time: when it happened, in minutes.
  • orderId: the order's unique identifier.
  • action: the action taken - only ACCEPT (starts billing) and FULFILL (ends billing) matter.

Output: return the Dasher's total pay (a double), rounded to two decimal places.

Worked example (Part 1):

Input events:

  • 06:15 | Order A | ACCEPT
  • 06:18 | Order B | ACCEPT
  • 06:36 | Order A | FULFILL
  • 06:45 | Order B | FULFILL

Calculation:

  • 06:15 - 06:18 (3 min): only order A active. Pay: 3 x 0.3 x 1 = 0.9
  • 06:18 - 06:36 (18 min): orders A and B active at the same time (stacked pay). Pay: 18 x 0.3 x 2 = 10.8
  • 06:36 - 06:45 (9 min): order A already done, only order B active. Pay: 9 x 0.3 x 1 = 2.7

Total pay: 0.9 + 10.8 + 2.7 = 14.4.

package com.example.demo;
import java.util.*;
public class DasherPaySolution {
    enum Action { ACCEPT, ARRIVE, PICKUP, FULFILL }
    static class Event {
        int time;
        String orderId;
        Action action;
        Event(int time, String orderId, Action action) {
            this.time = time;
            this.orderId = orderId;
            this.action = action;
        }
    }
    static class PeakWindow {
        int start, end;
        PeakWindow(int start, int end) {
            this.start = start;
            this.end = end;
        }
    }
    private static final double BASE_RATE_PER_MIN = 0.3;
    private static final Map<Action, Integer> ACTION_PRIORITY;
    static {
        Map<Action, Integer> map = new HashMap<>();
        map.put(Action.ACCEPT, 0);
        map.put(Action.ARRIVE, 1);
        map.put(Action.PICKUP, 2);
        map.put(Action.FULFILL, 3);
        ACTION_PRIORITY = Collections.unmodifiableMap(map);
    }
    private static void sortEventsStable(List<Event> events) {
        Collections.sort(events, new Comparator<Event>() {
            @Override
            public int compare(Event a, Event b) {
                if (a.time != b.time) return a.time - b.time;
                return ACTION_PRIORITY.get(a.action) - ACTION_PRIORITY.get(b.action);
            }
        });
    }
    // Part 1
    public static double calculateNaivePay(List<Event> events) {
        if (events == null || events.size() < 2) return 0.0;
        sortEventsStable(events);
        Set<String> activeOrders = new HashSet<>();
        double pay = 0.0;
        for (int i = 0; i < events.size() - 1; i++) {
            Event cur = events.get(i);
            if (cur.action == Action.ACCEPT) {
                activeOrders.add(cur.orderId);
            } else if (cur.action == Action.FULFILL) {
                activeOrders.remove(cur.orderId);
            }
            int a = cur.time, b = events.get(i + 1).time;
            double minutes = Math.max(0, b - a);
            pay += minutes * BASE_RATE_PER_MIN * activeOrders.size();
        }
        return round2(pay);
    }
    int a = cur.time, b = events.get(i + 1).time;
    double total = Math.max(0, b - a);
    if (total == 0) continue;
    int multiplicity = (atStoreOrder != null && activeOrders.contains(atStoreOrder))
        ? 1 : activeOrders.size();
    double rate = BASE_RATE_PER_MIN * multiplicity;
    double inPeak = 0.0;
    while (p < merged.size() && merged.get(p).end <= a) p++;
    int j = p;
    while (j < merged.size() && merged.get(j).start < b) {
        int s = Math.max(a, merged.get(j).start);
        int t = Math.min(b, merged.get(j).end);
        if (t > s) inPeak += (t - s);
        if (merged.get(j).end <= b) j++; else break;
    }
    inPeak = Math.min(inPeak, total);
    double nonPeak = total - inPeak;
    pay += nonPeak * rate + inPeak * rate * 2.0;
    }
    private static List<PeakWindow> mergePeakWindows(List<PeakWindow> peaks) {
        if (peaks == null || peaks.isEmpty()) return new ArrayList<>();
        List<PeakWindow> list = new ArrayList<>(peaks);
        Collections.sort(list, new Comparator<PeakWindow>() {
            @Override
            public int compare(PeakWindow a, PeakWindow b) {
                return a.start - b.start;
            }
        });
        List<PeakWindow> merged = new ArrayList<>();
        PeakWindow cur = list.get(0);
        for (int i = 1; i < list.size(); i++) {
            PeakWindow nxt = list.get(i);
            if (nxt.start <= cur.end) {
                cur = new PeakWindow(cur.start, Math.max(cur.end, nxt.end));
            } else {
                merged.add(cur);
                cur = nxt;
            }
        }
        merged.add(cur);
        return merged;
    }
    private static double round2(double x) {
        return Math.round(x * 100.0) / 100.0;
    }
    public static int toMinutes(String hhmm) {
        String[] t = hhmm.split(":");
        return Integer.parseInt(t[0]) * 60 + Integer.parseInt(t[1]);
    }
    public static void main(String[] args) {
        // --- Part 1 ---
        List<Event> part1Events = Arrays.asList(
            new Event(toMinutes("06:15"), "A", Action.ACCEPT),
            new Event(toMinutes("06:18"), "B", Action.ACCEPT),
            new Event(toMinutes("06:36"), "A", Action.FULFILL),
            new Event(toMinutes("06:45"), "B", Action.FULFILL)
        );
        System.out.println("[Part 1] Expected: $14.4, Actual: $" + calculateNaivePay(new ArrayList<Event>(part1Events)));
    }
}

Published

Curated and edited by PracHub

Practice the questions from this interview

Discussion

Sign in to join the discussion. The author is notified of every comment.

Loading comments…

Interview at a glance

Company
DoorDash
Role
Software Engineer
Rounds
Technical Screen
Outcome
Rejected
Difficulty
medium
Interview date
Mar 2026
Questions from this interview
1 question

Real DoorDash interview experiences

First-hand reports from DoorDash candidates — the rounds, the questions they were asked, and how it went.

All 50 DoorDash interview experiences