1894. 找到需要补充粉笔的学生编号
贴个题目:
贴个示例:
解题思路:
方法一:一次遍历+模拟
读完题目我们可以看出,其实就是循环派粉笔给学生,直到学生拿不到足够的粉笔,这时候就返回学生的位置。
那么我们可以先求循环一次学生需要多少支粉笔,然后求出派到最后一轮的时候,剩余的粉笔数。
最后就遍历一次数组,一边遍历,一边减少粉笔数,什么时候粉笔数是负数的时候,就证明这一个学生不够粉笔派了,此时返回这一个学生的下标即可。
优化:
我们可以通过取余数来求出最后一轮的时候剩余的粉笔数,这样子也能避免数据溢出
accumulate()函数是C++中的求和函数,详情可以看介绍:C++STL中的求和函数accumulate()
方法一代码:
class Solution {
public:
int chalkReplacer(vector<int>& chalk, int k) {
long long sum=accumulate(chalk.begin(),chalk.end(),0LL);
int reminder=k%sum;
int index=-1;
while(reminder>=0) reminder-=chalk[++index];
return index;
}
};
方法一性能分析:
时间分析:
一次遍历数组,因此时间复杂度是:O(n)
空间分析:
新建了常数个变量,因此空间复杂度是:O(1)
方法二:前缀和+二分查找
仔细阅读题目之后我们可以发现,其实求在最后一次派粉笔的时候,要求派的前n个同学的粉笔数大于k,此时就返回n这个校标即可。
那么根据以上的思路,我们可以使用前缀和求出前n个同学的粉笔数,然后在查找k的位置的时候,由于前缀和数组是递增数组,因此可以使用二分查找算法。
upper_bound()是C++中的二分查找函数,详细可以查看以下链接:C++STL中的upper_bound()函数的使用
方法二代码:
class Solution {
public:
int chalkReplacer(vector<int>& chalk, int k) {
if(chalk.front()>k) return 0;
for(int i=1;i<chalk.size();i++)
{
chalk[i]+=chalk[i-1];
if(chalk[i]>k) return i;
}
k%=chalk.back();
return upper_bound(chalk.begin(),chalk.end(),k)-chalk.begin();
}
};
方法二性能分析:
时间分析:
前缀和时间复杂度是:O(n),二分查找的时间复杂度是:O(logn),因此总的时间复杂度是取其最大值,为:O(n)
空间分析:
新建了常数个变量,因此空间复杂度是:O(1)
|