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

633 篇文章 23 订阅

给定一系列价格 [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的情况,

首先要判断,需要做多少次ceil操作(ceilmove)? 又需要做多少次floor操作(floormove)?

这两个问题很好解答,设之前计算的所有数组取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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值