🇮🇳
🇮🇳
Republic Day Special Offer!Get 20% OFF on all courses
Enroll Now
P
Prakalpana
📚Learn
Code Your Future
System Design⏱️ 20 min read📅 Jan 5

LLD: Design Elevator System - Multi-Elevator Scheduling

AK
Amit KumarSDE3 at Microsoft
📑 Contents (10 sections)

📌Problem Statement

Design an elevator system for a building with multiple elevators.

📌Requirements

  • N elevators in a building with M floors
  • Handle up/down requests from floors
  • Handle floor requests from inside elevator
  • Optimize for minimum wait time
  • Display current floor and direction
  • 📌Core Classes

    Enums and Constants

    public enum Direction {
    UP, DOWN, IDLE
    }
    public enum DoorState {
    OPEN, CLOSED, OPENING, CLOSING
    }
    public enum ElevatorState {
    MOVING, STOPPED, IDLE
    }

    Request Class

    public class Request {
    private int floor;
    private Direction direction;
    private long timestamp;
    public Request(int floor, Direction direction) {
    this.floor = floor;
    this.direction = direction;
    this.timestamp = System.currentTimeMillis();
    }
    }

    Elevator Class

    public class Elevator {
    private int id;
    private int currentFloor;
    private Direction direction;
    private ElevatorState state;
    private DoorState doorState;
    private TreeSet<Integer> upStops;
    private TreeSet<Integer> downStops;
    private int capacity;
    private int currentLoad;
    public Elevator(int id, int capacity) {
    this.id = id;
    this.capacity = capacity;
    this.currentFloor = 0;
    this.direction = Direction.IDLE;
    this.state = ElevatorState.IDLE;
    this.doorState = DoorState.CLOSED;
    this.upStops = new TreeSet<>();
    this.downStops = new TreeSet<>(Collections.reverseOrder());
    }
    public void addStop(int floor) {
    if (floor > currentFloor) {
    upStops.add(floor);
    } else if (floor < currentFloor) {
    downStops.add(floor);
    }
    updateDirection();
    }
    public void move() {
    if (state == ElevatorState.IDLE) return;
    if (direction == Direction.UP && !upStops.isEmpty()) {
    int nextStop = upStops.first();
    if (currentFloor < nextStop) {
    currentFloor++;
    }
    if (currentFloor == nextStop) {
    stop();
    upStops.remove(nextStop);
    }
    } else if (direction == Direction.DOWN && !downStops.isEmpty()) {
    int nextStop = downStops.first();
    if (currentFloor > nextStop) {
    currentFloor--;
    }
    if (currentFloor == nextStop) {
    stop();
    downStops.remove(nextStop);
    }
    }
    updateDirection();
    }
    private void stop() {
    state = ElevatorState.STOPPED;
    openDoor();
    try { Thread.sleep(3000); } catch (Exception e) {}
    closeDoor();
    state = ElevatorState.MOVING;
    }
    private void updateDirection() {
    if (upStops.isEmpty() && downStops.isEmpty()) {
    direction = Direction.IDLE;
    state = ElevatorState.IDLE;
    } else if (direction == Direction.UP && upStops.isEmpty()) {
    direction = Direction.DOWN;
    } else if (direction == Direction.DOWN && downStops.isEmpty()) {
    direction = Direction.UP;
    }
    }
    public int getStopsCount() {
    return upStops.size() + downStops.size();
    }
    }

    Elevator Controller

    public class ElevatorController {
    private List<Elevator> elevators;
    private int totalFloors;
    private ElevatorSelectionStrategy strategy;
    public ElevatorController(int numElevators, int floors) {
    this.elevators = new ArrayList<>();
    for (int i = 0; i < numElevators; i++) {
    elevators.add(new Elevator(i, 10));
    }
    this.totalFloors = floors;
    this.strategy = new NearestElevatorStrategy();
    }
    public void handleExternalRequest(int floor, Direction direction) {
    Elevator elevator = strategy.selectElevator(elevators, floor, direction);
    elevator.addStop(floor);
    }
    public void handleInternalRequest(int elevatorId, int floor) {
    Elevator elevator = elevators.get(elevatorId);
    elevator.addStop(floor);
    }
    }

    Selection Strategies

    public interface ElevatorSelectionStrategy {
    Elevator selectElevator(List<Elevator> elevators, int floor, Direction dir);
    }
    public class NearestElevatorStrategy implements ElevatorSelectionStrategy {
    public Elevator selectElevator(List<Elevator> elevators, int floor, Direction dir) {
    Elevator best = null;
    int minDistance = Integer.MAX_VALUE;
    for (Elevator e : elevators) {
    if (e.getDirection() == Direction.IDLE) {
    int dist = Math.abs(e.getCurrentFloor() - floor);
    if (dist < minDistance) {
    minDistance = dist;
    best = e;
    }
    }
    else if (e.getDirection() == dir) {
    if (dir == Direction.UP && e.getCurrentFloor() <= floor) {
    int dist = floor - e.getCurrentFloor();
    if (dist < minDistance) {
    minDistance = dist;
    best = e;
    }
    }
    else if (dir == Direction.DOWN && e.getCurrentFloor() >= floor) {
    int dist = e.getCurrentFloor() - floor;
    if (dist < minDistance) {
    minDistance = dist;
    best = e;
    }
    }
    }
    }
    if (best == null) {
    best = elevators.stream()
    .min(Comparator.comparingInt(Elevator::getStopsCount))
    .orElse(elevators.get(0));
    }
    return best;
    }
    }

    📌Design Patterns

  • 1Strategy Pattern: Elevator selection algorithm
  • 2State Pattern: Elevator states (Moving, Stopped, Idle)
  • 3Singleton: ElevatorController (optional)
  • 📌Interview Tips

  • Discuss scheduling algorithms (SCAN, LOOK)
  • Handle edge cases (overload, maintenance)
  • Explain concurrent request handling
  • Discuss priority for emergency floors
  • Classic question at Microsoft, Google, and Uber.

    AK

    Written by

    Amit Kumar

    SDE3 at Microsoft

    🚀 Master System Design

    Join 500+ developers

    Explore Courses →
    Chat on WhatsApp