青训营笔记3 | 豆包MarsCode AI刷题

140 阅读4分钟

问题描述

小明和 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内置的调试功能,通过在代码的关键位置设置断点,我们可以逐步跟踪程序的执行流程,观察变量的值变化,从而找出问题所在。通过调试可以帮助我们更深入地理解代码的执行逻辑,提高代码调试的效率。