[ 模运算 ] 6071. 完成所有任务需要的最少轮数

280 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情

每日刷题 2021.04.17

题目

  • 给你一个下标从 0 开始的整数数组 tasks ,其中 tasks[i] 表示任务的难度级别。在每一轮中,你可以完成 2 个或者 3 个相同难度级别的任务。
  • 返回完成所有任务需要的最少轮数,如果无法完成所有任务,返回-1

示例

  • 示例1
输入:tasks = [2,2,3,3,2,4,4,4,4,4]
输出:4
解释:要想完成所有任务,一个可能的计划是:
- 第一轮,完成难度级别为 2 的 3 个任务。 
- 第二轮,完成难度级别为 3 的 2 个任务。 
- 第三轮,完成难度级别为 4 的 3 个任务。 
- 第四轮,完成难度级别为 4 的 2 个任务。 
可以证明,无法在少于 4 轮的情况下完成所有任务,所以答案为 4 。
  • 示例2
输入:tasks = [2,3,3]
输出:-1
解释:难度级别为 2 的任务只有 1 个,但每一轮执行中,只能选择完成 2 个或者 3 个相同难度级别的任务。因此,无法完成所有任务,答案为 -1 。

提示

  • 1 <= tasks.length <= 10^5
  • 1 <= tasks[i] <= 10^9

解题思路

  • 最开始的思路,这道题easy,但是在比赛的时候竟然做了很长时间,比较恼火
  • 既然题目中要求的是,计算:最少轮数。那么基于贪心的思想,每次就要尽可能的将相同难度的任务3个一起完成。因此使用map集合统计了每个相同难度任务的个数,作为预处理。
  • 每次将相同难度的任务,先整除3,剩下的再拿去整除2。如果整除完3之后,不能整除2,那么就说明不能完成这个任务。
  • 提交后,wa了。错误样例:7。分析错误原因:7整除3之后,剩下1,按照之前的推论,那么这个任务就是不能够通过:完成 2 个或者 3 个相同难度级别完成。但是并不是这样的,7 = 3 * 1 + 2 * 2, 这样就可以完成。那么如何解决这个问题呢?(就有了下面的思路)

大佬点播后的思路

  • 需要的最少轮数,除以3之后的余数只有:0,1,2
    • 如果余数为0,那么就正好可以整除
    • 如果余数为1,那么除了1这种特殊情况不符合外,就需要还回去一个3,这样就可以凑成4,可以整除2
    • 如果余数为2,那么就正好可以整除2

AC代码

var minimumRounds = function(tasks) {
  const len = tasks.length;
  let map = new Map();
  for(const t of tasks) {
    map.set(t, (map.get(t) || 0) + 1);
  }
  // console.log(map)
  let res = 0,flag = true;
  map.forEach((value, key) => {
    if(value == 1) flag = false;
    let mod = value % 3,chu = parseInt(value / 3);
    if(flag){
      if(mod == 0){
        res += chu;
      }else if(mod == 1){
        res += chu + 1;
      }else if(mod == 2){
        res += chu + 1;
      }
    }
  });
  if(!flag) return -1;
  return res;
};

总结

  • 运用除法和模运算的题目,还需在做几道巩固。基础知识,不牢固。