Problem: Total Cost to Hire K Workers

You are given a 0-indexed integer array `costs` where `costs[i]` is the cost
of hiring the `ith` worker.

You are also given two integers `k` and `candidates`. We want to hire exactly
`k` workers according to the following rules:

* You will run `k` sessions and hire exactly one worker in each session.
* In each hiring session, choose the worker with the lowest cost from either the first `candidates` workers or the last `candidates` workers. Break the tie by the smallest index. 
* For example, if `costs = [3,2,7,7,1,2]` and `candidates = 2`, then in the first hiring session, we will choose the `4th` worker because they have the lowest cost `[3,2,7,7,1,2]`.
* In the second hiring session, we will choose `1st` worker because they have the same lowest cost as `4th` worker but they have the smallest index `[3,2,7,7,2]`. Please note that the indexing may be changed in the process.
* If there are fewer than candidates workers remaining, choose the worker with the lowest cost among them. Break the tie by the smallest index.
* A worker can only be chosen once.

Return the total cost to hire exactly `k` workers.


Python solution:
import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def totalCost(self, costs: List[int], k: int, candidates: int) -> int:
    ans = 0
    i = 0
    j = len(costs) - 1
    minHeapL = []
    minHeapR = []

    for _ in range(k):
      while len(minHeapL) < candidates and i <= j:
        heapq.heappush(minHeapL, costs[i])
        i += 1
      while len(minHeapR) < candidates and i <= j:
        heapq.heappush(minHeapR, costs[j])
        j -= 1
      if not minHeapL:
        ans += heapq.heappop(minHeapR)
      elif not minHeapR:
        ans += heapq.heappop(minHeapL)
      elif minHeapL[0] <= minHeapR[0]:
        ans += heapq.heappop(minHeapL)
      else:
        ans += heapq.heappop(minHeapR)

    return ans


Java solution:
class Solution {
  public long totalCost(int[] costs, int k, int candidates) {
    long ans = 0;
    int i = 0;
    int j = costs.length - 1;
    Queue<Integer> minHeapL = new PriorityQueue<>();
    Queue<Integer> minHeapR = new PriorityQueue<>();

    for (int hired = 0; hired < k; ++hired) {
      while (minHeapL.size() < candidates && i <= j)
        minHeapL.offer(costs[i++]);
      while (minHeapR.size() < candidates && i <= j)
        minHeapR.offer(costs[j--]);
      if (minHeapL.isEmpty())
        ans += minHeapR.poll();
      else if (minHeapR.isEmpty())
        ans += minHeapL.poll();
      // Both `minHeapL` and `minHeapR` are not empty.
      else if (minHeapL.peek() <= minHeapR.peek())
        ans += minHeapL.poll();
      else
        ans += minHeapR.poll();
    }

    return ans;
  }
}


C++ solution:
class Solution {
 public:
  long long totalCost(vector<int>& costs, int k, int candidates) {
    long ans = 0;
    int i = 0;
    int j = costs.size() - 1;
    priority_queue<int, vector<int>, greater<>> minHeapL;
    priority_queue<int, vector<int>, greater<>> minHeapR;

    for (int hired = 0; hired < k; ++hired) {
      while (minHeapL.size() < candidates && i <= j)
        minHeapL.push(costs[i++]);
      while (minHeapR.size() < candidates && i <= j)
        minHeapR.push(costs[j--]);
      if (minHeapL.empty())
        ans += minHeapR.top(), minHeapR.pop();
      else if (minHeapR.empty())
        ans += minHeapL.top(), minHeapL.pop();
      // Both `minHeapL` and `minHeapR` are not empty.
      else if (minHeapL.top() <= minHeapR.top())
        ans += minHeapL.top(), minHeapL.pop();
      else
        ans += minHeapR.top(), minHeapR.pop();
    }

    return ans;
  }
};