Minimize Rounding Error to Meet Target

medium greedy sorting array

Problem

Given an array of decimal price strings prices and an integer target, round each price either down (floor) or up (ceil) so that the sum of the rounded prices equals target. Minimize the total rounding error — the sum of |round(price) − price| — and return it as a string with exactly three decimals. If it is impossible to reach target, return "-1".

Inputprices = ["2.700", "3.400", "5.900"], target = 11
Output"1.200"
Floor sum = 2+3+5 = 10, so we must ceil exactly 1 price. Ceil 5.9→6 (error 0.1) and floor the rest: 2.7→2 (0.7), 3.4→3 (0.4). Total = 1.200.

import math

def minimize_error(prices, target):
    floor_sum = 0
    fracs = []
    for p in prices:
        v = float(p)
        floor_sum += math.floor(v)
        fracs.append(v - math.floor(v))
    up = target - floor_sum
    n = len(prices)
    if up < 0 or up > n:
        return "-1"
    fracs.sort(reverse=True)
    err = 0.0
    for i, f in enumerate(fracs):
        if i < up:
            err += 1 - f      # this price is rounded up
        else:
            err += f          # this price is rounded down
    return "%.3f" % err
function minimizeError(prices, target) {
  let floorSum = 0;
  const fracs = [];
  for (const p of prices) {
    const v = parseFloat(p);
    floorSum += Math.floor(v);
    fracs.push(v - Math.floor(v));
  }
  const up = target - floorSum;
  const n = prices.length;
  if (up < 0 || up > n) return "-1";
  fracs.sort((a, b) => b - a);
  let err = 0;
  for (let i = 0; i < n; i++) {
    if (i < up) err += 1 - fracs[i];   // rounded up
    else err += fracs[i];              // rounded down
  }
  return err.toFixed(3);
}
class Solution {
    public String minimizeError(String[] prices, int target) {
        int floorSum = 0;
        double[] fracs = new double[prices.length];
        for (int i = 0; i < prices.length; i++) {
            double v = Double.parseDouble(prices[i]);
            floorSum += (int) Math.floor(v);
            fracs[i] = v - Math.floor(v);
        }
        int up = target - floorSum, n = prices.length;
        if (up < 0 || up > n) return "-1";
        Arrays.sort(fracs);  // ascending
        double err = 0;
        for (int i = 0; i < n; i++) {
            // largest 'up' fracs (at the end) are rounded up
            if (i >= n - up) err += 1 - fracs[i];
            else err += fracs[i];
        }
        return String.format("%.3f", err);
    }
}
string minimizeError(vector<string>& prices, int target) {
    int floorSum = 0, n = prices.size();
    vector<double> fracs;
    for (auto& p : prices) {
        double v = stod(p);
        floorSum += (int)floor(v);
        fracs.push_back(v - floor(v));
    }
    int up = target - floorSum;
    if (up < 0 || up > n) return "-1";
    sort(fracs.rbegin(), fracs.rend());  // descending
    double err = 0;
    for (int i = 0; i < n; i++) {
        if (i < up) err += 1 - fracs[i];   // rounded up
        else err += fracs[i];              // rounded down
    }
    char buf[32];
    snprintf(buf, sizeof(buf), "%.3f", err);
    return string(buf);
}
Time: O(n log n) Space: O(n)