1058. Minimize Rounding Error to Meet Target

Given an array of prices [p1,p2...,pn] and a target, round each price pi to Roundi(pi) so that the rounded array [Round1(p1),Round2(p2)...,Roundn(pn)] sums to the given target. Each operation Roundi(pi) could be either Floor(pi) or Ceil(pi).

Return the string "-1" if the rounded array is impossible to sum to target. Otherwise, return the smallest rounding error, which is defined as Σ |Roundi(pi) - (pi)| for i from 1 to n, as a string with three places after the decimal.

 

Example 1:

Input: prices = ["0.700","2.800","4.900"], target = 8
Output: "1.000"
Explanation:
Use Floor, Ceil and Ceil operations to get (0.7 - 0) + (3 - 2.8) + (5 - 4.9) = 0.7 + 0.2 + 0.1 = 1.0 .

Example 2:

Input: prices = ["1.500","2.500","3.500"], target = 10
Output: "-1"
Explanation: It is impossible to meet the target.

Example 3:

Input: prices = ["1.500","2.500","3.500"], target = 9
Output: "1.500"

 

Constraints:

  • 1 <= prices.length <= 500
  • Each string prices[i] represents a real number in the range [0.0, 1000.0] and has exactly 3 decimal places.
  • 0 <= target <= 106

Rust Solution

struct Solution;

impl Solution {
    fn minimize_error(prices: Vec<String>, target: i32) -> String {
        let prices: Vec<f64> = prices
            .into_iter()
            .map(|x| x.parse::<f64>().unwrap())
            .collect();
        let floor: i32 = prices.iter().map(|x| x.floor() as i32).sum();
        let ceil: i32 = prices.iter().map(|x| x.ceil() as i32).sum();
        let n = prices.len();
        if target < floor || target > ceil {
            return "-1".to_string();
        }
        let m = (target - floor) as usize;
        let mut diff = vec![];
        for i in 0..n {
            if prices[i].floor() as i32 != prices[i].ceil() as i32 {
                diff.push(prices[i].ceil() as f64 - prices[i]);
            }
        }
        let mut sum = 0.0;
        diff.sort_by(|a, b| a.partial_cmp(&b).unwrap());
        for i in 0..diff.len() {
            if i < m {
                sum += diff[i];
            } else {
                sum += 1.0 - diff[i];
            }
        }

        format!("{:.3}", sum)
    }
}

#[test]
fn test() {
    let prices = vec_string!["0.700", "2.800", "4.900"];
    let target = 8;
    let res = "1.000".to_string();
    assert_eq!(Solution::minimize_error(prices, target), res);
    let prices = vec_string!["1.500", "2.500", "3.500"];
    let target = 10;
    let res = "-1".to_string();
    assert_eq!(Solution::minimize_error(prices, target), res);
}

Having problems with this solution? Click here to submit an issue on github.