# 题目: 1894. 找到需要补充粉笔的学生编号
一个班级里有 n
个学生,编号为 0
到 n - 1
。每个学生会依次回答问题,编号为 0
的学生先回答,然后是编号为 1
的学生,以此类推,直到编号为 n - 1
的学生,然后老师会重复这个过程,重新从编号为 0
的学生开始回答问题。
给你一个长度为 n
且下标从 0
开始的整数数组 chalk
和一个整数 k
。一开始粉笔盒里总共有 k
支粉笔。当编号为 i 的学生回答问题时,他会消耗 chalk[i] 支粉笔。如果剩余粉笔数量 严格小于 chalk[i]
,那么学生 i
需要 补充 粉笔。
请你返回需要 补充 粉笔的学生 编号 。
# 题解1: 模拟的优化
记一次遍历完所有学生,所需的粉笔数为 sum, 用 k % sum 则为最后一轮的粉笔数。
最后一轮依次遍历,找出需要补充粉笔的学生编号。
# 代码
var chalkReplacer = function(chalk, k) {
// 一次所需的粉笔数
let sum = chalk.reduce((pre,now)=>pre+now)
let left = k%sum,right=0;
for(let i=0;i<chalk.length;i++){
right += chalk[i]
if(left<right) return i
}
};
# 题解2: 前缀和 + 二分查找
使用 前缀和 + 二分查找 来优化第二次的遍历
注意: 关于前缀和数组中可能会超出32位整数, 为了避免溢出,在计算前缀和时,将其与k进行比较,
# 代码
var chalkReplacer = function(chalk, k) {
if(chalk[0] > k) return 0
// 前缀和
for(let i=1;i<chalk.length;i++){
chalk[i] += chalk[i-1]
if(chalk[i]>k) return i
}
let sum = chalk[chalk.length-1]
let target = k%sum;
let left=0, right=chalk.length-1;
while(left<right){
let mid = left+Math.floor((right-left)/2)
if(target >= chalk[mid]) left = mid+1
else right = mid
}
return left;
};