LeetCode 题解工作台

雇佣 K 位工人的总代价

给你一个下标从 0 开始的整数数组 costs ,其中 costs[i] 是雇佣第 i 位工人的代价。 同时给你两个整数 k 和 candidates 。我们想根据以下规则恰好雇佣 k 位工人: 总共进行 k 轮雇佣,且每一轮恰好雇佣一位工人。 在每一轮雇佣中,从最前面 candidates 和最后…

category

4

题型

code_blocks

5

代码语言

hub

3

相关题

当前训练重点

中等 · 双·指针·invariant

bolt

答案摘要

我们首先判断 $candidates \times 2$ 是否大于等于 ,如果是,我们直接返回前 个最小的工人的代价之和。 否则,我们使用一个小根堆 来维护前 个工人和后 个工人的代价。

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 双·指针·invariant 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给你一个下标从 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 = [17,12,10,2,7,2,11,20,8], k = 3, candidates = 4
输出:11
解释:我们总共雇佣 3 位工人。总代价一开始为 0 。
- 第一轮雇佣,我们从 [17,12,10,2,7,2,11,20,8] 中选择。最小代价是 2 ,有两位工人,我们选择下标更小的一位工人,即第 3 位工人。总代价是 0 + 2 = 2 。
- 第二轮雇佣,我们从 [17,12,10,7,2,11,20,8] 中选择。最小代价是 2 ,下标为 4 ,总代价是 2 + 2 = 4 。
- 第三轮雇佣,我们从 [17,12,10,7,11,20,8] 中选择,最小代价是 7 ,下标为 3 ,总代价是 4 + 7 = 11 。注意下标为 3 的工人同时在最前面和最后面 4 位工人中。
总雇佣代价是 11 。

示例 2:

输入:costs = [1,2,4,1], k = 3, candidates = 3
输出:4
解释:我们总共雇佣 3 位工人。总代价一开始为 0 。
- 第一轮雇佣,我们从 [1,2,4,1] 中选择。最小代价为 1 ,有两位工人,我们选择下标更小的一位工人,即第 0 位工人,总代价是 0 + 1 = 1 。注意,下标为 1 和 2 的工人同时在最前面和最后面 3 位工人中。
- 第二轮雇佣,我们从 [2,4,1] 中选择。最小代价为 1 ,下标为 2 ,总代价是 1 + 1 = 2 。
- 第三轮雇佣,少于 3 位工人,我们从剩余工人 [2,4] 中选择。最小代价是 2 ,下标为 0 。总代价为 2 + 2 = 4 。
总雇佣代价是 4 。

 

提示:

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

解题思路

方法一:优先队列(小根堆)

我们首先判断 candidates×2candidates \times 2 是否大于等于 nn,如果是,我们直接返回前 kk 个最小的工人的代价之和。

否则,我们使用一个小根堆 pqpq 来维护前 candidatescandidates 个工人和后 candidatescandidates 个工人的代价。

我们首先将前 candidatescandidates 个工人的代价以及对应的下标加入小根堆 pqpq 中,然后将后 candidatescandidates 个工人的代价以及对应的下标加入小根堆 pqpq 中。用两个指针 llrr 分别指向前后待选工人的下标,初始时 l=candidatesl = candidates, r=ncandidates1r = n - candidates - 1

然后我们进行 kk 次循环,每次从小根堆 pqpq 中取出代价最小的工人,将其代价加入答案,如果 l>rl > r,说明前后待选工人已经全部被选完,直接跳过。否则,如果当前工人的下标小于 ll,说明是前面的工人,我们将第 ll 个工人的代价以及下标加入小根堆 pqpq 中,然后 ll 加一;否则,我们将第 rr 个工人的代价以及下标加入小根堆 pqpq 中,然后 rr 减一。

循环结束后,返回答案即可。

时间复杂度 O(n×logn)O(n \times \log n),空间复杂度 O(n)O(n)。其中 nn 是数组 costscosts 的长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution:
    def totalCost(self, costs: List[int], k: int, candidates: int) -> int:
        n = len(costs)
        if candidates * 2 >= n:
            return sum(sorted(costs)[:k])
        pq = []
        for i, c in enumerate(costs[:candidates]):
            heappush(pq, (c, i))
        for i in range(n - candidates, n):
            heappush(pq, (costs[i], i))
        heapify(pq)
        l, r = candidates, n - candidates - 1
        ans = 0
        for _ in range(k):
            c, i = heappop(pq)
            ans += c
            if l > r:
                continue
            if i < l:
                heappush(pq, (costs[l], l))
                l += 1
            else:
                heappush(pq, (costs[r], r))
                r -= 1
        return ans
speed

复杂度分析

指标
时间O((k + m) \cdot\log m)
空间O(m)
psychology

面试官常问的追问

外企场景
  • question_mark

    Candidate should understand the two-pointer approach and the use of minheaps in optimization problems.

  • question_mark

    Look for candidates who are comfortable with tracking invariant conditions across array segments.

  • question_mark

    Watch for the ability to efficiently calculate costs using heaps without unnecessary comparisons.

warning

常见陷阱

外企场景
  • error

    Failing to maintain the invariant that the two pointers represent valid candidate ranges for selection.

  • error

    Using only one heap and not considering the left and right parts of the array efficiently.

  • error

    Not optimizing the heap operations, leading to suboptimal performance.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Consider different candidate ranges (not just two sides of the array) for more complex scenarios.

  • arrow_right_alt

    Use a single heap in certain cases to test if a simpler solution might be more efficient for smaller input sizes.

  • arrow_right_alt

    Introduce variations where the workers are ordered differently to test the efficiency of heap-based approaches.

help

常见问题

外企场景

雇佣 K 位工人的总代价题解:双·指针·invariant | LeetCode #2462 中等