LeetCode Solutions

855. Exam Room

Time: Constructor: $O(1)$, seat(): $O(n)$, leave(p: int): $O(1)$

Space: $O(n)$

			

class ExamRoom {
 public:
  ExamRoom(int N) : N(N) {}

  int seat() {
    if (students.empty()) {
      students.push_back(0);
      map[0] = begin(students);
      return 0;
    }

    int prevStudent = -1;
    int maxDistToClosest = 0;
    int val = 0;              // Inserted val
    list<int>::iterator pos;  // Inserted position

    for (auto it = begin(students); it != end(students); ++it) {
      if (prevStudent == -1) {   // doesn't insert before
        maxDistToClosest = *it;  // Distance between it and the begining
        pos = it;
      } else if ((*it - prevStudent) / 2 > maxDistToClosest) {
        maxDistToClosest = (*it - prevStudent) / 2;
        val = (*it + prevStudent) / 2;
        pos = it;
      }
      prevStudent = *it;
    }

    if (N - 1 - students.back() > maxDistToClosest) {
      pos = end(students);
      val = N - 1;
    }

    map[val] = students.insert(pos, val);
    return val;
  }

  void leave(int p) {
    students.erase(map[p]);
  }

 private:
  int N;
  list<int> students;
  unordered_map<int, list<int>::iterator> map;  // {p: student iterator}
};
			

class Node {
  public Node prev;
  public Node next;
  public int value;

  public Node(int value) {
    this.value = value;
  }
}

class ExamRoom {
  public ExamRoom(int N) {
    this.N = N;
    join(head, tail);
  }

  public int seat() {
    if (head.next == tail) {
      Node node = new Node(0);
      join(head, node);
      join(node, tail);
      map.put(0, node);
      return 0;
    }

    int prevStudent = -1;
    int maxDistToClosest = 0;
    int val = 0;     // Inserted val
    Node pos = null; // Inserted position

    for (Node node = head; node != tail; node = node.next) {
      if (prevStudent == -1) {         // doesn't insert before
        maxDistToClosest = node.value; // Distance between it and the begining
        pos = node;
      } else if ((node.value - prevStudent) / 2 > maxDistToClosest) {
        maxDistToClosest = (node.value - prevStudent) / 2;
        val = (node.value + prevStudent) / 2;
        pos = node;
      }
      prevStudent = node.value;
    }

    if (N - 1 - tail.prev.value > maxDistToClosest) {
      pos = tail;
      val = N - 1;
    }

    Node insertedNode = new Node(val);
    join(pos.prev, insertedNode);
    join(insertedNode, pos);

    map.put(val, insertedNode);

    return val;
  }

  public void leave(int p) {
    Node removedNode = map.get(p);
    join(removedNode.prev, removedNode.next);
  }

  private int N;
  private Node head = new Node(-1);
  private Node tail = new Node(-1);
  private Map<Integer, Node> map = new HashMap<>(); // {p: student iterator}

  private void join(Node node1, Node node2) {
    node1.next = node2;
    node2.prev = node1;
  }

  private void remove(Node node) {
    join(node.prev, node.next);
  }
}