问题描述
小明和 n 个小朋友一起玩游戏,n 个小朋友站成一排,小明站在最右边的位置。
小明先给 n 个小朋友各分配了 a[1]、a[2]、a[3]... a[n] 个糖果,最左边的是第 1 个。
现在还剩下 m 个糖果,小明制定了这样的分配规则:
m 个糖果会一个一个的分配。
每个糖果会先给第 1 个小朋友,如果小朋友拥有的糖果(加上分配的糖果)数量小于等于右边的小朋友,则这个小朋友会拥有这个糖果。
如果这个小朋友拥有的糖果(加上分配的糖果)数量大于右边的小朋友,则这个糖果会传递给右边的小朋友。
一直重复这个过程,如果传递到第 n 个小朋友,第 n 个小朋友不太喜欢糖果,他会直接把糖果给小明,所以第 n 个小朋友的糖果数量会保持不变。
请帮忙找出第 m 个糖果会分配给哪个小朋友。
输入格式
每个样例有两行。
第一行是整数 n 和 m ;(3≤n≤1000,1≤m≤10^9)
第二行是 n 个整数 a[i] ;(1≤a[i]≤10^7)
输出格式
每个样例一行,整数 k ,表示第 m 个糖果分给了第 k 个小朋友,如果是小明获得了糖果,则输出 n + 1 。
输入样例1
4 3
1 2 3 4
输出样例1
1
输入样例2
4 2
4 3 2 3
输出样例2
5
数据范围
(1≤𝑡≤100)
(3≤n≤1000,1≤m≤10^9)
(1≤a[i]≤10^7)
问题分析
题目要求得到第m个糖果被分给了谁,我们遍历的时候就以糖果的数量作为循环的终止条件。
每次循环的时候,都是从第一个小孩开始发糖果,判断该小朋友拥有的糖果+1的数量是否小于等于右边的小朋友,如果是,则将糖果分给该小孩,更新糖果数组a的值和剩余糖果m的值,再判断m是否等于0,如果等于就返回该小孩的位置。
如果该小朋友拥有的糖果+1的数量大于右边的小朋友,就继续循环遍历,直到找到满足条件的小朋友,将糖果分给该小孩,更新糖果数组a的值和剩余糖果m的值,再判断m是否等于0,如果等于就返回该小孩的位置。重复此流程即可得出结果。
C++代码实现
int solution(int n, int m, std::vector<int> a) {
// Edit your code here
int i = 0;
while(m > 0)
{
if(a[i] + 1 <= a[i+1])
{
a[i]++;
m--;
if ( m == 0){return i+1;}
}
else{
while( i < n-1 &&a[i] + 1 > a[i+1] ){
i++;
}
if(i == n-1){return n+1;}
a[i]++;
m--;
if ( m == 0){return i+1;}
i =0 ;
}
}
return i;
}
题目总结
注意数组边界
- 在代码中,数组的索引是从
0开始,n-1结束的,我们在代码中使用了索引i和i+1。所以在访问数组元素时,我们要确保i和i + 1的索引没有越界。 - 例如,
if (a[i] + 1 <= a[i+1])这一条件需要确保i不能超过n - 2,否则访问a[i + 1]会超出数组的范围。
理清终止条件
while (m > 0)这一循环的终止条件为剩余糖果都分发完,即m == 0。if (m == 0) { return i + 1; }这一段代码在每次更新数组后都会检查是否 分发完了糖果,如果是,则返回当前的小朋友i + 1。- 如果在数组的某一部分找不到合适的更新位置(即无法满足
a[i] + 1 <= a[i + 1]),则i会继续增加,直到找到可以修改的元素位置,或者i达到数组的末尾。 - 如果
i == n - 1,说明我们已经到达数组的最后一项,此时返回n + 1,表示糖果还给了小明。
善于使用Marscode中的断点调试
在运行代码的时候,如果发现得到的结果和预期输出不一致,我们可以使用Marscode内置的调试功能,通过在代码的关键位置设置断点,我们可以逐步跟踪程序的执行流程,观察变量的值变化,从而找出问题所在。通过调试可以帮助我们更深入地理解代码的执行逻辑,提高代码调试的效率。