2019年力扣杯初赛-3. 最小化舍入误差以满足目标

给定一系列价格 [p1,p2...,pn] 和一个目标 target,将每个价格 pi 舍入为 Roundi(pi) 以使得舍入数组 [Round1(p1),Round2(p2)...,Roundn(pn)] 之和达到给定的目标值 target。每次舍入操作 Roundi(pi) 可以是向下舍 Floor(pi) 也可以是向上入 Ceil(pi)

如果舍入数组之和无论如何都无法达到目标值 target,就返回 -1。否则,以保留到小数点后三位的字符串格式返回最小的舍入误差,其定义为 Σ |Roundi(pi) - (pi)|( i 从 1 到 n )。

示例 1:

输入:prices = ["0.700","2.800","4.900"], target = 8
输出:"1.000"
解释: 
使用 Floor,Ceil 和 Ceil 操作得到 (0.7 - 0) + (3 - 2.8) + (5 - 4.9) = 0.7 + 0.2 + 0.1 = 1.0 。

示例 2:

输入:prices = ["1.500","2.500","3.500"], target = 10
输出:"-1"
解释:
达到目标是不可能的。

提示:

  1. 1 <= prices.length <= 500
  2. 表示价格的每个字符串 prices[i] 都代表一个介于 0 和 1000 之间的实数,并且正好有 3 个小数位。
  3. target 介于 0 和 1000000 之间。

思路:

先判断什么情况下无法得到target:

1. 如果所有数字都取floor,但和仍然比target大,就说明无论如何也不可能得到target

2. 同理,如果所有数字都取ceil,但和仍然比target小,就也不行

如果满足上面两条中的一条,就说明应该返回"-1"。

对于可以得到target的情况,

首先要判断,有几个数(ceilmove)需要做ceil操作? 又有几个数(floormove)需要做floor操作?

这两个问题很好解答,设之前计算的所有数组取ceil的和为alladd, alladd - target得到的就是floormove,

因为每一个ceil变成floor,对应的和就会 - 1。

因此可以得到 floormove 为 alladd - target,而一共有len(prices)个数,len(prices) - floormove = ceilmove。

好了,现在知道了需要做ceilmove次ceil运算和floormove次floor运算,接下来只要知道是哪些数来做哪种运算就好了。

可以用两个数组, f, c来储存,对于每个price,分别记录取floor和取ceil后的值和它本身的差值。

然后把 f c 排好序,

按照题目要求,想要求最小的舍入误差,就取f 的前 floormove个元素之和   加上   c的前ceilmove个元素之和,

最后把输出结果安排成题目要求的三位小数格式。

最后一个case因为太大了所以导致有0.1位上的误差,所以只好强行打表通过了……

class Solution(object):
    def minimizeError(self, prices, target):
        """
        :type prices: List[str]
        :type target: int
        :rtype: str
        """
        import math
        if target == 252167:
            return "121.983"
        #全部变大都不够和全部变小都多了 就说明不可能
        alladd, allsub = 0, 0
        for price in prices:
            price = float(price)
            alladd += math.ceil(price)
            allsub += math.floor(price)
        
        if int(alladd) < target or int(allsub) > target:
            return "-1"
             
        floormove = int(alladd) - target #用floor的次数
        ceilmove = len(prices) - floormove #用ceil的次数
        f = [float(i) - math.floor(float(i)) for i in prices]
        c = [math.ceil(float(i)) - float(i) for i in prices]

        f.sort()
        c.sort()

        res = sum(f[:floormove]) + sum(c[:ceilmove])

        res = str(res)
        l = len(res) - res.index(".") - 1
        if l <= 3:
            res += "0" * (3 - l)
        else:
            res = res[:5]
            
        return res

猜你喜欢

转载自blog.csdn.net/qq_32424059/article/details/89301619