LeetCode Solutions

1058. Minimize Rounding Error to Meet Target

Time: $O(n\log n)$

Space: $O(n)$

			

class Solution {
 public:
  string minimizeError(vector<string>& prices, int target) {
    // A[i] := (costCeil - costFloor, costCeil, costFloor)
    // The lower the costCeil - costFloor, the cheaper to ceil it
    vector<tuple<double, double, double>> A;
    int sumFloored = 0;
    int sumCeiled = 0;

    for (const string& p : prices) {
      const double price = stod(p);
      const int floored = floor(price);
      const int ceiled = ceil(price);
      sumFloored += floored;
      sumCeiled += ceiled;
      const double costFloor = price - static_cast<double>(floored);
      const double costCeil = static_cast<double>(ceiled) - price;
      A.emplace_back(costCeil - costFloor, costCeil, costFloor);
    }

    if (sumFloored > target || sumCeiled < target)
      return "-1";

    sort(begin(A), end(A));

    double sumError = 0.0;
    const int nCeiled = target - sumFloored;
    for (int i = 0; i < nCeiled; ++i)
      sumError += get<1>(A[i]);
    for (int i = nCeiled; i < A.size(); ++i)
      sumError += get<2>(A[i]);

    stringstream ss;
    ss << std::fixed << std::setprecision(3) << sumError;
    return ss.str();
  }
};
			

class Solution {
  public String minimizeError(String[] prices, int target) {
    // A[i] := (costCeil - costFloor, costCeil, costFloor)
    // The lower the costCeil - costFloor, the cheaper to ceil it
    List<double[]> A = new ArrayList<>();
    int sumFloored = 0;
    int sumCeiled = 0;

    for (final String p : prices) {
      final double price = Double.parseDouble(p);
      final int floored = (int) Math.floor(price);
      final int ceiled = (int) Math.ceil(price);
      sumFloored += floored;
      sumCeiled += ceiled;
      final double costFloor = price - (double) floored;
      final double costCeil = (double) ceiled - price;
      A.add(new double[] {costCeil - costFloor, costCeil, costFloor});
    }

    if (sumFloored > target || sumCeiled < target)
      return "-1";

    Collections.sort(A, new Comparator<double[]>() {
      @Override
      public int compare(double[] a, double[] b) {
        return Double.compare(a[0], b[0]);
      }
    });

    double sumError = 0.0;
    final int nCeiled = target - sumFloored;
    for (int i = 0; i < nCeiled; ++i)
      sumError += A.get(i)[1];
    for (int i = nCeiled; i < A.size(); ++i)
      sumError += A.get(i)[2];

    return String.format("%.3f", sumError);
  }
}
			

class Solution:
  def minimizeError(self, prices: List[str], target: int) -> str:
    # A[i] := (costCeil - costFloor, costCeil, costFloor)
    # The lower the costCeil - costFloor, the cheaper to ceil it
    A = []
    sumFloored = 0
    sumCeiled = 0

    for price in map(float, prices):
      floored = math.floor(price)
      ceiled = math.ceil(price)
      sumFloored += floored
      sumCeiled += ceiled
      costFloor = price - floored
      costCeil = ceiled - price
      A.append((costCeil - costFloor, costCeil, costFloor))

    if not sumFloored <= target <= sumCeiled:
      return '-1'

    A.sort()
    nCeiled = target - sumFloored
    return '{:.3f}'.format(sum(a[1] for a in A[:nCeiled]) +
                           sum(a[2] for a in A[nCeiled:]))