题目描述
有n个小朋友围坐成一圈。老师给每个小朋友随机发偶数个糖果,然后进行下面的游戏:
每个小朋友都把自己的糖果分一半给左手边的孩子。
一轮分糖后,拥有奇数颗糖的孩子由老师补给1个糖果,从而变成偶数。
反复进行这个游戏,直到所有小朋友的糖果数都相同为止。
你的任务是预测在已知的初始糖果情形下,老师一共需要补发多少个糖果。输入
程序首先读入一个整数N(2< N< 100),表示小朋友的人数。
接着是一行用空格分开的N个偶数(每个偶数不大于1000,不小于2)输出
要求程序输出一个整数,表示老师需要补发的糖果数。
样例输入
3 2 2 4样例输出
4
思路分析:
首先,看见这个问题,我第一反应就是用递归。因为它每次需要执行的内容都是一样的,先分后补,判断是否相等。
然后在写代码的过程中,需要注意几个问题:
1、从左到右分糖果,我将其理解为从后往前分糖果,然后第一个分给最后一个。此时因为第一个小朋友手里的糖果状态已经是和第二个小朋友分过之后的,我们不能直接使用这个数值,所以我就新创了一个数组brr,让brr=arr,那么,我们就可以用brr[0]来代替执行后的arr[0]。
2、判断数组里每个数值是否相等后,需要考虑到此时数组arr已经是排序之后的状态,就相当于把小朋友们按照手里糖果的数量从小到大进行了排队,当然如果不相等的话,那么我们此时再将arr数组带入到下一轮代码的执行是不合理的,所以在排序前需要将brr数组格式化,完全等于arr数组。最后在判断完之后,我们再对arr数组进行复原即可。
代码展示:
import java.util.Scanner;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] arr = new int[n];
int[] brr = new int[n];
for (int i=0 ; i<n ; i++) {
arr[i] = sc.nextInt();
brr[i] = arr[i];
}
int count=0;
System.out.println(ar(arr,brr,n,count));
}
public static int ar(int[] arr,int[] brr,int n,int count) {
for (int i=0;i<n;i++) { //转圈互分糖果
if (i==(n-1)) {
//此时arr[0]已经是和arr[1]互分糖果后的数值,但是我们需要的是原始值,所以借用brr数组
arr[i] = (arr[i]/2)+(brr[0]/2);
} else {
arr[i] = (arr[i]/2)+(arr[i+1]/2);
}
}
for (int i=0;i<n;i++) { //判断每个人手里的糖果是否为奇数
if (arr[i]%2!=0) {
arr[i] = arr[i]+1;
count ++;
}
//相当于格式化brr数组,因为我们需要用到brr[0]和下面对arr数组排序之后的恢复
brr[i] = arr[i];
}
// 对arr数组进行排序,如果收尾相等,则课判断该数组的每一个元素值都是相等的
Arrays.sort(arr);
// 如果相等,我们直接输出计数器
if (arr[0]==arr[n-1]) {
return count;
}
// 如果不相等,我们需要对排序之后的arr数组进行复原,然后循环执行
for (int i=0;i<n;i++) {
arr[i] = brr[i];
}
return ar(arr,brr,n,count);
}
}
测评状态: