初学python记录:力扣2462. 雇佣 K 位工人的总代价

题目:

给你一个下标从 0 开始的整数数组 costs ,其中 costs[i] 是雇佣第 i 位工人的代价。

同时给你两个整数 k 和 candidates 。我们想根据以下规则恰好雇佣 k 位工人:

  • 总共进行 k 轮雇佣,且每一轮恰好雇佣一位工人。
  • 在每一轮雇佣中,从最前面 candidates 和最后面 candidates 人中选出代价最小的一位工人,如果有多位代价相同且最小的工人,选择下标更小的一位工人。
    • 比方说,costs = [3,2,7,7,1,2] 且 candidates = 2 ,第一轮雇佣中,我们选择第 4 位工人,因为他的代价最小 [3,2,7,7,1,2] 。
    • 第二轮雇佣,我们选择第 1 位工人,因为他们的代价与第 4 位工人一样都是最小代价,而且下标更小,[3,2,7,7,2] 。注意每一轮雇佣后,剩余工人的下标可能会发生变化。
  • 如果剩余员工数目不足 candidates 人,那么下一轮雇佣他们中代价最小的一人,如果有多位代价相同且最小的工人,选择下标更小的一位工人。
  • 一位工人只能被选择一次。

返回雇佣恰好 k 位工人的总代价。

提示:

  • 1 <= costs.length <= 105
  • 1 <= costs[i] <= 105
  • 1 <= k, candidates <= costs.length

思考:

暴力解法

招k个人即为k次循环,每次判断待选人与candidates的大小关系,选出题意所需的最小花销和员工索引,从待选人中去掉该员工,进行下一次循环。每次花销相加即为结果,代码如下:

class Solution(object):
    def totalCost(self, costs, k, candidates):
        """
        :type costs: List[int]
        :type k: int
        :type candidates: int
        :rtype: int
        """
        n = len(costs)
        ans = 0
        for _ in range(k):
            if n < candidates:
                # 如果剩余员工数目不足 candidates 人,那么下一轮雇佣他们中代价最小的一人,如果有多位代价相同且最小的工人,选择下标更小的一位工人。
                min_value = min(costs)
                index = costs.index(min_value)
                ans += min_value
                costs.pop(index)
                n -= 1
            else:
                # 在每一轮雇佣中,从最前面 candidates 和最后面 candidates 人中选出代价最小的一位工人,如果有多位代价相同且最小的工人,选择下标更小的一位工人。
                min_value = 10 ** 6
                for i in range(candidates):
                    if costs[i] < min_value:
                        min_value = costs[i]
                        index = i
                for j in range(n - candidates, n):
                    if costs[j] < min_value:
                        min_value = costs[j]
                        index = j
                ans += min_value
                costs.pop(index)
                n -= 1
        return ans

提交超时,卡在第 132 / 162  个例子:

优化——最小堆

1. 设n为costs数组的长度(即候选人数量),若n - candidates*2 < k,则我们选取的k个人一定是整个costs数组中最小的k个数,所以直接返回最小的k个数的和即可;

2. 否则,分别用两个最小堆储存 前candidates个元素后candidates个元素,每次比较两个最小堆的堆顶元素,选更小的从堆顶弹出并加到ans,并向堆中填充对应位置的新元素。直到选完k个人为止。

代码如下:

class Solution(object):
    def totalCost(self, costs, k, candidates):
        """
        :type costs: List[int]
        :type k: int
        :type candidates: int
        :rtype: int
        """
        n = len(costs)    # 待选人数量
        ans = 0
        if n < candidates*2 + k:
            costs.sort()
            return sum(costs[:k])

        wait_1 = costs[:candidates]     # 前candidates个元素
        wait_2 = costs[-candidates:]     # 后candidates个元素
        # 转成最小堆的形式
        heapify(wait_1)
        heapify(wait_2)

        left = candidates
        right = n - 1 - candidates
        for _ in range(k):
            # 比较两个最小堆堆顶元素,选更小的弹出并加到ans,并向堆中填充对应位置的新元素
            if wait_1[0] <= wait_2[0]:
                ans += heapreplace(wait_1, costs[left])
                left += 1
            else:
                ans += heapreplace(wait_2, costs[right])
                right -= 1
        return ans

提交通过:

 

 

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值