[M前缀和] lc1894. 找到需要补充粉笔的学生编号(二分+模拟+坑点)

Posted Ypuyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[M前缀和] lc1894. 找到需要补充粉笔的学生编号(二分+模拟+坑点)相关的知识,希望对你有一定的参考价值。

1. 题目来源

链接:1894. 找到需要补充粉笔的学生编号

2. 题目解析

有个坑点,有点恶心。首先被数据坑一把,需要开 LL,然后被边界坑一把…

先求前缀和,然后 ka[n-1] 取模,然后二分出小于等于 k 的最大值即可。注意,然后就被坑了。 因为小于等于 k 意味着当前同学可以用完粉笔,下一个同学不能用完粉笔,然后就需要返回 l+1然而在 k 在对 a[n-1] 取模的时候,以及初始情况都可能导致 k<a[0],此时当然应该返回 a[0],然而直接返回 a[l+1] 等价于返回 a[1] 肯定是错误的。

所以,二分完之后,a[l] 并不一定是小于等于 k 的,也就是 l+1 这个人并不一定是最终答案,l 也可能是答案。


当然,得到总和,取模之后完全不必要二分。直接遍历一遍,到哪个人粉笔不够了,当然就要输出那个人的编号了。这样就不需要额外开空间了。


  • 时间复杂度 O ( n ) O(n) O(n)
  • 空间复杂度 O ( 1 ) O(1) O(1)

class Solution {
public:
    int chalkReplacer(vector<int>& chalk, int k) {
        using LL = long long;
        int n = chalk.size();
        vector<LL> a; 
        for (auto e : chalk) a.push_back(e);
        for (int i = 1; i < n; i ++ ) a[i] += a[i - 1];
        k %= a[n - 1];
        int l = 0, r = n - 1;
        while (l < r) {                         // 二分小于等于 k 的最大的一个位置
            int mid = l + r + 1 >> 1;
            if (a[mid] > k) r = mid - 1;
            else l = mid;
        }

        // 如果小于等于 k,那么是下一个同学铅笔不够,即返回l+1,否则就是本同学铅笔不够
        // 值得注意的是,二分停下来的位置按理说一定是 a[l]<=k 的
        // 下面这个三目运算符怎么会取到 a[l]>k 的情况呢?
        // 实际上因为有 k%=a[n - 1]这个操作,可能会导致 a[0]>k,导致需要返回 0 下标,
        // 所有的 a[mid]>k,导致右边界一直缩小到 l,此时 l=r=0
        // 所以唯一的情况就是当第一个 a[0]>k 时,二分才会停在 0 的位置,返回l=r=0即可,
        // 其它情况都是 a[l]<=k,需要返回 l+1 或者 r+1
        // if (a[0] > k) return 0;
        // return a[l] <= k ? l + 1 : l - 1000; 后面的不会被执行到
        return a[l] <= k ? l + 1 : l;
    }
};

go 代码

func chalkReplacer(chalk []int, k int) int {
    n := len(chalk)
    sum := 0
    for i := 0; i < n; i ++ {
        sum += chalk[i]
    }

    k %= sum
    for i := 0; i < n; i ++ {
        if chalk[i] > k {
            return i
        }
        k -= chalk[i]
    }

    return -1
}

以上是关于[M前缀和] lc1894. 找到需要补充粉笔的学生编号(二分+模拟+坑点)的主要内容,如果未能解决你的问题,请参考以下文章

1894. 找到需要补充粉笔的学生编号

1894. 找到需要补充粉笔的学生编号

力扣每日一题 1894. 找到需要补充粉笔的学生编号

Leetcode刷题100天—1894. 找到需要补充粉笔的学生编号( 数组)—day34

Leetcode刷题100天—1894. 找到需要补充粉笔的学生编号( 数组)—day34

LeetCode 1894 找到需要补充粉笔的学生编号[取余] HERODING的LeetCode之路