小工具知识网

当前位置: 首页 > 行业知识 > 【Py/Java/C++三种语言OD2023C卷真题】20天拿下华为OD笔试之【二分查找】2023C-项目排期【欧弟算法】全网注释最详细分类最全的华为OD真题题解

行业知识

【Py/Java/C++三种语言OD2023C卷真题】20天拿下华为OD笔试之【二分查找】2023C-项目排期【欧弟算法】全网注释最详细分类最全的华为OD真题题解

2026-11-05 07:51:52 来源:互联网转载

���LeetCode算法/华为OD考试扣扣交流群可加 948025485

()

可上全网独家的 欧弟OJ系统 练习华子OD、大厂真题

绿色聊天软件戳 od1336了解算法冲刺训练

()

文章目录

  • 题目描述与示例
    • 题目描述
    • 输入描述
    • 输出描述
    • 示例
      • 输入
      • 输出
      • 说明
      • 解题思路
      • 代码
        • python
        • java
        • cpp
        • 时空复杂度
        • 华为OD算法/大厂面试高频题算法练习冲刺训练

          题目描述与示例

          题目描述

          项目组共有N个开发人员,项目经理接到了M个独立的需求,每个需求的工作量不同,且每个需求只能由一个开发人员独立完成,不能多人合作。假定各个需求之间无任何先后依赖关系,请设计算法帮助项目经理进行工作安排,使整个项目能用最少的时间交付。

          输入描述

          第一行输入为M个需求的工作量,单位为天,用逗号隔开。

          例如:X1 X2 X3 … Xm 。表示共有M个需求,每个需求的工作量分别为X1天,X2天…Xm天。

          其中0

          第二行输入为项目组人员数量N

          输出描述

          最快完成所有工作的天数

          示例

          输入

          6 2 7 7 9 3 2 1 3 11 42

          输出

          28

          说明

          共有两位员工,其中一位分配需求 6 2 7 7 3 2 1 共需要28天完成,另一位分配需求 9 3 11 4 共需要27天完成,故完成所有工作至少需要28天。

          解题思路

          又是一道描述相当晦涩的题目(很想骂人)

          用比较简洁的数学语言来描述就是,将数组X1, X2, X3, ... ,Xm分为N部分(并非子数组,不要求连续),设每一部分的和为sum1, sum2, ..., sumN,要求找到一种分配方式使得max(sum1, sum2, ..., sumN)最小。

          用一句简单的话来说,就是最小化各部分求和的最大值。这种设问一定要想到用二分来完成。

          将问题转化为,我们需要找到一个阈值k(一个人的最大工作量),并将原数组nums可以被分为N部分(分配给N个人),使得这N部分的各自求和的最大值都不会超过k(每个人各自的工作量不会超过k)。

          显然k的选择是一个二段性问题:

          • 当k非常大时,原数组nums无论如何分配都可以完成要求
          • 当k非常小时,原数组nums无论怎么分配都无法完成要求
          • 必然存在一个临界值k,使得存在nums的分配结果恰好完成要求。

            我们希望找到这个阈值k,因此需要对k进行二分查找,二分查找的范围为[max(nums), sum(nums)]。当

            • k = max(nums)时,能够被分为m = len(nums)部分(需要m个人来完成所有工作)
            • k = sum(nums)时,能够被分为1部分(只由1个人可以完成所有工作)

              而上述二分过程的贪心子问题为:当我们选择了阈值k时,数组nums能否被分割不超过N部分?

              这个问题就和【贪心】2023B-数据最节约的备份方法几乎完全一致了,其代码为

               def sub_question(k, nums, m, N):    ans = 0    check = [0] * m    for i in range(m):        if check[i] == 1:            continue        ans += 1        cur_sum = 0        j = i        while j  k:                j += 1            else:                cur_sum += nums[j]                check[j] = 1                j += 1    return ans  k:                j += 1            # 如果第j份工作和当前员工之前的工作量之和不超过k            # 则贪心地将这份工作安排给这个员工            # 修改cur_sum和check[j],j递增            else:                cur_sum += nums[j]                check[j] = 1                j += 1    # 退出循环时,如果需要的人数ans不超过N,则返回True,否则返回False    return ans     // 贪心子问题    private static boolean subQuestion(int k, int[] nums, int m, int N) {        int ans = 0;        int[] check = new int[m];        for (int i = 0; i  num) {        nums.push_back(num);    }    int m = nums.size();    int N;    cin >> N;    sort(nums.begin(), nums.end(), greater());    int left = nums[0], right = accumulate(nums.begin(), nums.end(), 0) + 1;    while (left 

上一篇:怎么传资料到服务器?

下一篇:Python-VBA函数之旅-str函数