二分: 最短评估时间 | 豆包MarsCodeAI刷题

75 阅读3分钟

题目链接

最短评估时间

前置知识

  • 二分查找
    一种高效的查找方法,是用来在一个有序数组中查找某一元素的算法
    以数组nums = [1,2,3,4,5,6]为例,我们比较顺序查找和二分查找6的效率
    • 顺序查找:遍历数组,需要进行6次的比较 最坏情况下即O(n)O(n)
    • 二分查找:
      1. 首先定位数组中间3, 6 > 3 那么答案必不在3的左边, 下次从 4开始搜索
      2. 定位5,此时6 > 5 答案必在5的右边,从6开始搜索
      3. 定位6,查找结束 二分查找的复杂度是多少? 每次会减少当前范围的一遍 则为O(logn)O(log n) 默认为2为底

从小数据并不能看出二分的效率,但当n足够大且为最坏情况,如n = 1e8,假设比较一个数需要1秒,那么顺序查找需要100000000s 大约需要 1157天才能找到,而二分查找只需要27s

简单实现

nums := []int{1, 2, 3, 4, 5, 6}
target := 6
l, r := 0, len(nums)
for l < r {
    mid := l + (r-l)/2
    if nums[mid] == target {
       fmt.Println("index:", mid)
       break
    } else if nums[mid] > target {
       r = mid
    } else {
       l = mid + 1
    }
}

解题思路

  • 简化题意:找到最少评估所有学生的时间, m名教师评估时间为数组a, 学生有n
  • 考虑,如果我们给一个非常大的时间,比如t=10000,怎么知道能评估完?

每个教师评估一个学生需要a[i]分钟,老师是同时工作的,我们目前是t分钟

只需要用1mt/a[i] \sum_1^m t / a[i](小数忽略,因为不够评估一个人), 然后判断评估的人数是否超过了给定的人数n

  • 知道了如何计算在t分钟内能够评估多少人,考虑如何得到最少时间

t分钟满足要求时,那么大于t分钟肯定也是可以的,我们就不需要考虑了,此时答案在[1,t]
此时小于t分钟,评估完和未评估完都可能,我们利用二分的思想去找中间时间

假设当前中间时间为mid 如果 mid 评估的人数>= n 则答案在左边 [1,mid]

新一轮 l分钟 ,评估人数小于<n 则答案在右边[l+1,mid]

思路很清晰了,我们考虑评估的上界是多少(最多评估多少分钟)?
n种方法:
1. 评估最慢的老师评估n名学生的时间 必然是合适的值之一
2. 无脑设置一个足够大的数,比如 1e9 0xffffff INT_MAX等,可以根据数据范围制定
3. ....

最少需要多久(下界)? 至少1分钟吧
上下界范围不需要非常明确,只需要保证答案一定在这个范围内即可,但也不能过于离谱

题解代码

func solution(N int, M int, A []int) int {
    l,r  := 0, 0xfffff
    ans :=0 
    for l < r {
        mid := l+(r-l)/2
        cnt := 0
        for _, v := range A {
            cnt += mid / v
        }
        if cnt >= N {
            ans= mid
            r = mid
        }else {
            l = mid + 1
        }
    }
    return ans
}
def solution(N, M, A):
    l, r = 0, 0xfffff
    ans = 0
    while l < r:
        mid = l + (r - l) // 2
        cnt = 0
        for v in A:
            cnt += mid // v
        if cnt >= N:
            ans = mid
            r = mid
        else:
            l = mid + 1
    return ans