返回介绍

solution / 1600-1699 / 1665.Minimum Initial Energy to Finish Tasks / README

发布于 2024-06-17 01:03:16 字数 4744 浏览 0 评论 0 收藏 0

1665. 完成所有任务的最少初始能量

English Version

题目描述

给你一个任务数组 tasks ,其中 tasks[i] = [actuali, minimumi] :

  • actuali 是完成第 i 个任务 需要耗费 的实际能量。
  • minimumi 是开始第 i 个任务前需要达到的最低能量。

比方说,如果任务为 [10, 12] 且你当前的能量为 11 ,那么你不能开始这个任务。如果你当前的能量为 13 ,你可以完成这个任务,且完成它后剩余能量为 3 。

你可以按照 任意顺序 完成任务。

请你返回完成所有任务的 最少 初始能量。

 

示例 1:

输入:tasks = [[1,2],[2,4],[4,8]]
输出:8
解释:
一开始有 8 能量,我们按照如下顺序完成任务:
  - 完成第 3 个任务,剩余能量为 8 - 4 = 4 。
  - 完成第 2 个任务,剩余能量为 4 - 2 = 2 。
  - 完成第 1 个任务,剩余能量为 2 - 1 = 1 。
注意到尽管我们有能量剩余,但是如果一开始只有 7 能量是不能完成所有任务的,因为我们无法开始第 3 个任务。

示例 2:

输入:tasks = [[1,3],[2,4],[10,11],[10,12],[8,9]]
输出:32
解释:
一开始有 32 能量,我们按照如下顺序完成任务:
  - 完成第 1 个任务,剩余能量为 32 - 1 = 31 。
  - 完成第 2 个任务,剩余能量为 31 - 2 = 29 。
  - 完成第 3 个任务,剩余能量为 29 - 10 = 19 。
  - 完成第 4 个任务,剩余能量为 19 - 10 = 9 。
  - 完成第 5 个任务,剩余能量为 9 - 8 = 1 。

示例 3:

输入:tasks = [[1,7],[2,8],[3,9],[4,10],[5,11],[6,12]]
输出:27
解释:
一开始有 27 能量,我们按照如下顺序完成任务:
  - 完成第 5 个任务,剩余能量为 27 - 5 = 22 。
  - 完成第 2 个任务,剩余能量为 22 - 2 = 20 。
  - 完成第 3 个任务,剩余能量为 20 - 3 = 17 。
  - 完成第 1 个任务,剩余能量为 17 - 1 = 16 。
  - 完成第 4 个任务,剩余能量为 16 - 4 = 12 。
  - 完成第 6 个任务,剩余能量为 12 - 6 = 6 。

 

提示:

  • 1 <= tasks.length <= 105
  • 1 <= actual​i <= minimumi <= 104

解法

方法一:贪心 + 自定义排序

我们假设任务数为 $n$,初始能量值为 $E$,考虑完成最后一个任务,这需要我们完成前 $n-1$ 个任务后,剩余的能量值不小于完成最后一个任务需要达到的能量值 $m_n$,即:

$$ E-\sum_{i=1}^{n-1} a_i \geq m_n $$

我们可以将 $m_n$ 表示成 $a_n+(m_n - a_n)$,然后将上面的式子变形,得到:

$$ E-\sum_{i=1}^{n-1} a_i \geq a_n+(m_n - a_n) $$

整理可得:

$$ E \geq \sum_{i=1}^{n} a_i + (m_n - a_n) $$

其中 $\sum_{i=1}^{n} a_i$ 是固定不变的,要使得初始值能量值 $E$ 最小,我们需要让 $m_n - a_n$ 最小,即 $a_n-m_n$ 最大。

因此,我们可以将任务按照 $a_i-m_i$ 从小到大排序。然后从前往后遍历任务,对于每个任务,如果当前能量值 $cur$ 小于 $m_i$,则需要增加能量值 $m_i - cur$,使得当前能量值刚好等于 $m_i$,然后再完成任务,更新 $cur = cur - a_i$。继续遍历,直到完成所有任务,即可得到初始所需的最少能量值。

时间复杂度 $O(n\times \log n)$。其中 $n$ 为任务数。忽略排序的空间开销,空间复杂度 $O(1)$。

class Solution:
  def minimumEffort(self, tasks: List[List[int]]) -> int:
    ans = cur = 0
    for a, m in sorted(tasks, key=lambda x: x[0] - x[1]):
      if cur < m:
        ans += m - cur
        cur = m
      cur -= a
    return ans
class Solution {
  public int minimumEffort(int[][] tasks) {
    Arrays.sort(tasks, (a, b) -> a[0] - b[0] - (a[1] - b[1]));
    int ans = 0, cur = 0;
    for (var task : tasks) {
      int a = task[0], m = task[1];
      if (cur < m) {
        ans += m - cur;
        cur = m;
      }
      cur -= a;
    }
    return ans;
  }
}
class Solution {
public:
  int minimumEffort(vector<vector<int>>& tasks) {
    sort(tasks.begin(), tasks.end(), [&](const auto& a, const auto& b) { return a[0] - a[1] < b[0] - b[1]; });
    int ans = 0, cur = 0;
    for (auto& task : tasks) {
      int a = task[0], m = task[1];
      if (cur < m) {
        ans += m - cur;
        cur = m;
      }
      cur -= a;
    }
    return ans;
  }
};
func minimumEffort(tasks [][]int) (ans int) {
  sort.Slice(tasks, func(i, j int) bool { return tasks[i][0]-tasks[i][1] < tasks[j][0]-tasks[j][1] })
  cur := 0
  for _, task := range tasks {
    a, m := task[0], task[1]
    if cur < m {
      ans += m - cur
      cur = m
    }
    cur -= a
  }
  return
}
function minimumEffort(tasks: number[][]): number {
  tasks.sort((a, b) => a[0] - a[1] - (b[0] - b[1]));
  let ans = 0;
  let cur = 0;
  for (const [a, m] of tasks) {
    if (cur < m) {
      ans += m - cur;
      cur = m;
    }
    cur -= a;
  }
  return ans;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文