每个输入包含一个测试用例。每个测试用例的第一行包含一个整数 n(1 <= n <= 100),接下来的一行包含 n 个整数 ai(1 <= ai <= 100)。
输出一行表示最少需要移动多少次可以平分苹果,如果方案不存在则输出 -1。
4 7 15 9 5
3
思路很简单,先按条件过滤:(1) 总数不能平分为n份返回false;(2) 有奶牛所拥有的苹果数和总体平均数奇偶性不同返回false。
这样双指针走过的区域一定是已经分配完毕的区域,双指针走完后检查一下第一头奶牛和最后一头奶牛拥有的苹果数是不是都为平均数就可以了。
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.util.Arrays; public class Main { public static void main(String[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line; while((line = br.readLine()) != null){ int n = Integer.parseInt(line); String[] strs = br.readLine().split(" "); int[] apples = new int[n]; System.out.println(solve(strs, apples, n)); } } private static int solve(String[] strs, int[] apples, int n){ int total = 0; for(int i = 0; i < n; i++){ apples[i] = Integer.parseInt(strs[i]); total += apples[i]; } if(total % n != 0){ return -1; // 无法平分成n份 }else{ int goal = total / n; for(int i = 0; i < n; i++){ if(((apples[i] + goal) & 1) != 0){ return -1; // 有一只奶牛的苹果数与目标苹果数奇偶性不同 } } Arrays.sort(apples); int L = lowerBound(apples, goal); int R = upperBound(apples, goal); if(apples[L] == goal){ L--; } int times = 0; while(L >= 0 && R < n){ int diff = apples[R] - goal; if(apples[L] + diff == goal){ apples[L--] += diff; apples[R++] -= diff; times += diff >> 1; }else if(apples[L] + diff < goal){ apples[L] += diff; apples[R++] -= diff; times += diff >> 1; }else{ diff = goal - apples[L]; apples[R] -= diff; apples[L--] += diff; times += diff >> 1; } } return apples[0] == goal && apples[n - 1] == goal? times: -1; } } private static int lowerBound(int[] nums, int target) { int left = 0, right = nums.length - 1, index = 0; while(left < right){ int mid = left + ((right - left) >> 1); if(nums[mid] > target){ right = mid - 1; }else{ index = mid; left = mid + 1; } } return index; } private static int upperBound(int[] nums, int target) { int left = 0, right = nums.length - 1, index = 0; while(left < right){ int mid = left + ((right - left) >> 1); if(nums[mid] <= target){ left = mid + 1; }else{ right = mid; } } return left; } }
import java.io.*; import java.util.*; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); String[] strs = br.readLine().split(" "); int[] arr = new int[n]; int sum = 0; for(int i = 0; i < n; i++){ arr[i] = Integer.parseInt(strs[i]); sum += arr[i]; } if(sum % n != 0 || n == 1){ System.out.println(n == 1? 0: -1); }else{ int target = sum / n; int less = 0, more = 0; boolean flag = true; for(int i = 0; i < n; i++){ if((Math.abs(target - arr[i]) & 1) != 0){ flag = false; break; } if(arr[i] < target){ less += target - arr[i]; }else if(arr[i] > target){ more += arr[i] - target; } } if(less != more){ flag = false; } System.out.println(flag? less >> 1: -1); } } }
import java.util.*; public class Main{ public static void main (String[] args) { Scanner cin = new Scanner(System.in); int num = cin.nextInt(); int[] nums = new int[num]; for (int i = 0; i < num; i++) { nums[i] = cin.nextInt(); } // 数学方法解决 System.out.println(resolve(nums)); } private static int resolve(int[] nums) { // 总数 int sum = 0; // 平均数 int average = 0; for (int num : nums) { sum += num; } // 如果无法整除 if (sum % nums.length != 0) { return -1; } // 如果整除后的结果与原数组中的奇偶性不一致 if(sum/nums.length%2!=nums[0]%2){ return -1; } // 判断每个数是否同为奇数或者同为偶数 for (int i = 0; i < nums.length; i++) { if (nums[i]%2!=nums[0]%2){ return -1; } } average = sum / nums.length; int count = 0; // 计算每个数要到达平均数的次数,全部加起来然后除以4 for (int num : nums) { count += Math.abs(num - average); } return count / 4; } }
import java.util.Arrays; import java.util.Scanner; // 思路:先算总和记平均值,如果除不尽,返回-1, // 如果平均值为奇数但是数组里有偶数,返回-1,如果数组里有奇数,平均值为偶数返回-1; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int num = scanner.nextInt(); int[] arr = new int[num]; for (int i = 0; i < num; i++) { arr[i] = scanner.nextInt(); } System.out.println(divideApples(arr)); } private static int divideApples(int[] arr) { if (arr.length == 0) { return -1; } if (arr.length == 1) { return 0; } int sum = 0; // 苹果总数 int sin = 0; // 奇数总数 int dou = 0; // 偶数总数 for (int i = 0; i < arr.length; i++) { if (arr[i]%2 == 1) { sin++; } else { dou++; } sum+=arr[i]; } if (sum%arr.length!=0) { return -1; } int average = sum/arr.length; if (average%2==0&&sin>0) { return -1; } if (average%2==1&&dou>0) { return -1; } int count = 0; // 转移次数 Arrays.sort(arr);//先排序 int i = arr.length - 1; int j = 0; while (i>j) { while (arr[i] > average && arr[j] < average) { arr[i]-=2; arr[j]+=2; count++; } if (arr[i]==average) { i--; } if (arr[j] == average) { j++; } } return count; } }
// 导包部分,考虑记忆问题,直接使用*代替一切 import java.io.*; import java.lang.*; import java.util.*; public class Main{ public static void main(String[] args) throws IOException { // 固定部分,读取输入 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(reader.readLine()); if( n < 1 || n > 100){ System.out.print(-1); return; } String[] x = reader.readLine().split(" "); if(x.length != n){ System.out.print(-1); return; } /** * 解题思路: * 1、公式: 增加次数 = 减少次数, 所以只要求增加次数综合,或者减少次数总和 * 2、条件约束: * 2.1 要么全部是双数,要么全部是单数 * 2.2 如何判断全部双数或者单数,根据第一个数字作为参考,后续每一个数字必须与第一个类型一致,使用标志位changeNum * 2.3 总数 应该能够 被总个数整除,即 sum % n == 0 * 3、利用平均数计算每一个数需要移动的次数,根据公式,只需要计算增加次数 ,或者是减少次数即可 */ int changeNum = 0; int sum = 0; for(int i=0; i<n; i++){ int value = Integer.parseInt(x[i]); //双数 if( value%2 == 0){ if(changeNum == 0 || changeNum == 1){ //被第一个双数占用,后续元素不能出现单数 changeNum = 1; }else { System.out.print(-1); return; } }else{ if(changeNum == 0 || changeNum == 2){ //被第一个双数占用,后续元素不能出现单数 changeNum = 2; }else { System.out.print(-1); return; } } sum = sum + Integer.parseInt(x[i]); } if(sum % n != 0){ System.out.print(-1); return; } test(n, x, sum); } public static void test(int n, String[] x, int sum){ int moveNum = 0; int avd = sum / n; for(int i=0; i<n;i++){ int ivalue = Integer.parseInt(x[i]); if(ivalue < avd){ moveNum = moveNum + (avd - ivalue)/2; } } System.out.print(moveNum); } }
import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] cow = new int[n]; for(int i = 0;sc.hasNext();i++){ cow[i] = sc.nextInt(); } int sum = 0; for(int j = 0;j<cow.length;j++){ sum+=cow[j]; } int avg = 0; int k = -1; if(sum%cow.length!=0){ System.out.println(k); return; } avg = sum/cow.length; for(int i:cow){ if((i-avg)%2!=0){ System.out.println(k); return; } } int apple = 0; int c = 0; for(int i:cow){ c = i-avg; if(c>0) apple += c; } k = apple/2; System.out.println(k); } }
import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); while(sc.hasNext()){ int n = sc.nextInt(); int[] arr = new int[n]; int sum = 0; for(int i = 0; i < n; i++){ arr[i] = sc.nextInt(); sum += arr[i]; } boolean flag = true; flag &= sum % n == 0; int res = 0; if(flag){ int temp = sum / n; for(int i = 0; i < n; i++){ if((arr[i] - temp) % 2 != 0){ flag = false; break; }else{ if(arr[i] - temp >= 0){ res += (arr[i] - temp) / 2; } } } } System.out.println(flag ? res : -1); } } }
import java.util.*; public class Main { /* * n 只奶牛坐在一排,每个奶牛拥有 ai 个苹果,现在你要在它们之间转移苹果,使得最后所有奶牛拥有的苹果数都相同, * 每一次,你只能从一只奶牛身上拿走恰好两个苹果到另一个奶牛上,问最少需要移动多少次可以平分苹果,如果方案不存在输出 -1。 输入描述: * 每个输入包含一个测试用例。每个测试用例的第一行包含一个整数 n(1 <= n <= 100),接下来的一行包含 n 个整数 ai(1 <= ai <= * 100)。 */ public static void main(String[] args) { // TODO Auto-generated method stub Scanner cin = new Scanner(System.in); int n = cin.nextInt();// 拥有苹果的奶牛数量(奶牛都开始学会分享了 太可怕了) int a[] = new int[n]; int sum = 0;//总苹果数 int out = 0;//移动次数 for (int i = 0; i < n; i++) { a[i] = cin.nextInt(); sum = sum + a[i];//总苹果数 } int temp = sum / n; if (sum % n != 0) { System.out.print(-1); } else { int x = 0; for (int i = 0; i < n; i++) { if (Math.abs(a[i] - temp) % 2 != 0) { //System.out.print(-1); x = 1; break; } } if (x == 0) { for (int i = 0; i < n; i++) { if (a[i] < temp) { out = out + ((temp - a[i]) / 2); // System.out.println(temp+" "+((temp-a[i])/2)); } } System.out.print(out); } else { System.out.print(-1); } } } }
/**看了前几名的解答方法都是比较有技巧性的,我是直接用的贪心算法的思路, 没那么多的技巧性,大家可以看看。贪心决策ru 1.把数据排序(小->大) 2.每次把当前最大的数-2 最小的数+2;移动次数+1 3.加减过程中,如果最小的数出现>平均值或最大的数小于平均值,直接返回-1;
import java.util.Arrays; import java.util.Scanner; /** * @author JT.L * @date 2019/8/28 20:54:53 * @description */ public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { int n = Integer.parseInt(scanner.nextLine()); String[] strings = scanner.nextLine().split(" "); int[] a = new int[strings.length]; for (int i = 0; i < strings.length; i++) { a[i] = Integer.parseInt(strings[i]); } System.out.println(solution(a)); } } private static int solution(int[] a) { int moveTimes = 0; int failure = -1; int moveApple = 2; Arrays.sort(a); int average = 0; for (int i = 0; i < a.length; i++) { average += a[i]; } // 不能整除人数 返回-1 if (average%a.length!=0){ return failure; } average /= a.length; for (int i = 0, j = a.length - 1; i < j; ) { while (a[i] != average) { if (a[i] > average || a[j] < average) { return failure; } if (a[j] > average) { a[i] += moveApple; a[j] -= moveApple; moveTimes++; } else if (a[j] == average) { j--; } } i++; } return moveTimes; } }
import java.io.IOException; import java.io.BufferedReader; import java.io.InputStreamReader; public class Main { /** *这个题目是求解最少的移动次数。细节上考虑,是要将一个奶牛身上的苹果转移到另一个奶牛身上,但是实际上求最小,并不需要一个一个的转移。 *奶牛拥有的少于平均多少个,除以二就是最少需要的次数。遍历所有的奶牛,计算少于平均的奶牛需要多少个就可以了,如果想省略判断是否少于平均, *也是可以的,直接用奶牛拥有的苹果个数减去平均值,取绝对值除2就可以了,但是由于多的也计算,少的也计算,那么最后要将总的次数除以二。 *注意细节问题: *一:如果总苹果sum( = a1 + a2 + .. + an)不能整除奶牛个数n,则无法平均,无解 *二:每次只能从一个奶牛上恰好拿2个到另一个奶牛,这个和数字运算有关,奇数和偶数减2仍然保持自身奇偶性, *但是平均数只可能是奇数或者偶数中的一种,所以输入的每个数必须和平均数保持一致奇偶性,否则无解。 */ public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); boolean haveOdd = false; boolean haveEven = false; int sum = 0; int avg = 0; int numNo = Integer.parseInt(br.readLine().trim()); int[] arrNum = new int[numNo]; String[] arrInput = br.readLine().trim().split(" "); int step = 0; for (int i=0; i<numNo; i++) { arrNum[i] = Integer.parseInt(arrInput[i]); sum += arrNum[i]; if (arrNum[i] % 2 == 0) { haveEven = true; } else { haveOdd = true; } } if (sum % numNo != 0) {//不能整除 System.out.println(-1); return; } avg = sum /numNo; if (((avg % 2 == 0) && haveOdd == true) || ((avg % 2 == 1) && haveEven == true)) {//判断每个数和avg的奇偶性是否一致 System.out.println(-1); return; } for (int i=0; i<numNo; i++) {//核心运算 if (arrNum[i] < avg) { step += (avg - arrNum[i]) >> 1;//除以2 } } System.out.println(step); } }
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n=scanner.nextInt(); int[] array=new int[n]; array[0]=scanner.nextInt(); int sum=array[0]; for(int i=1;i<n;i++){ array[i]=scanner.nextInt(); //第一个条件:所有数的奇偶性必须是一样的 if(((array[i-1]^array[i])&1)==1){ System.out.println(-1); return; } sum+=array[i]; } //第二个条件:n能够整除sum if(sum%n!=0){ System.out.println(-1); return; } int average=sum/n; //第三个条件:均值的奇偶性和数的奇偶性相同 if(((array[0]^average)&1)==1){ System.out.println(-1); return; } int differ=0; for(int i=0;i<n;i++){ differ+=Math.max(0, average-array[i]); } System.out.println(differ/2); } }
分享一个超简单的思路:
首先要明确一点:所有苹果的总数加起来应该可以整除奶牛的数量,否则怎么分都不可能平均。
以这个作为前提,那么每只奶牛(当前的苹果数-平均数)/2即为移动的次数,只有当加苹果的次数等于捡苹果的次数,才算有解。
``` import java.util.ArrayList; import java.util.Scanner; public class Main { public static void main(String args[]) { Scanner input = new Scanner(System.in); while (input.hasNextInt()) { int n = input.nextInt(); //若只有一只奶牛,则移动0次获得平均 if (n == 1) { System.out.println(0); break; } ArrayListInteger> list = new ArrayList(n); for (int i = 0; i n; i++) { list.add(input.nextInt()); } //求平均值 int average = list.stream().mapToInt(x -> x).sum() / n; //加苹果的次数 int addCount = 0; //减苹果的次数 int reduceCount = 0; for (Integer integer : list) { if (integer > average) { addCount += (integer - average) / 2; } else if (integer average) { reduceCount += (average - integer) / 2; } } if (addCount == reduceCount && addCount != 0) System.out.println(addCount); else System.out.println(-1); } input.close(); } }
先计算总和可以均分否? 再计算差值是否可以均分, 最后计算差值移动次数。public class SplitApple {
import java.util.*;
public class Main65 {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
int[] a=new int[n];
int sum=0;
int count=0;
int[] flag=new int[n];
for(int i=0;i<n;i++) {
a[i]=scanner.nextInt();
sum+=a[i];
}
if(sum%n!=0) {
System.out.println("-1");
}else {
int ave=sum/n;
for(int i=0;i<n;i++) {
if(a[i]<ave) {
flag[i]=1;
}else if(a[i]==ave) {
flag[i]=0;
}else {
flag[i]=-1;
}
}
for(int i=0;i<n;i++) {
if(flag[i]==-1) {
while(a[i]>ave) {
a[i]=a[i]-2;
count++;
}
if(a[i]<ave) {
count=-1;
break;
}
}else if(flag[i]==1) {
while(a[i]<ave) {
a[i]=a[i]+2;
count++;
}
if(a[i]>ave) {
count=-1;
break;
}
}
}
if(count==-1) {
System.out.println(count+"");
}else {
System.out.println(count/2+"");
}
}
}
}
if---else
import java.util.Arrays; import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String line = scanner.nextLine(); int n = Integer.parseInt(line); line = scanner.nextLine(); String []s = line.split(" "); int []arr = new int[n]; for (int i = 0;i < n;i ++) { arr[i] = Integer.parseInt(s[i]); } System.out.println(step(arr)); } public static int step(int []arr) { int n = arr.length; int sum = 0; //统计和,计算平均值 for (int i = 0;i < n;i ++) { sum += arr[i]; } int ave = sum/n; //如果不能整除,说明无法分配 if (ave * n != sum) { return -1; } //如果和平均值的差值不为偶数,那么就失败 for (int i = 0;i < n;i ++) { if ((arr[i] - ave) % 2 != 0) { return -1; } } //排序数组,以便从大到小统计 Arrays.sort(arr); int rem = 0; //统计溢出的值 for (int i = n - 1;i >= 0;i --) { if (arr[i] - ave >= 2) { rem += arr[i] - ave; arr[i] = ave; } } //将溢出值按需分配。从最小的开始分,如果最小的都满足不了,那就gg int count = 0;//统计次数 for (int i = 0;i < n;i ++) { int val = arr[i]; while (val < ave && rem > 0) { count ++; rem -= 2; val += 2; } if (val != ave) { return -1; } } return count; } }
判断分苹果是否必然会失败,判断条件来源有两个:
奶牛的苹果数之和无法被奶牛数整除, 或者说每个奶牛的苹果数的平均值不是个整数
虽然能通过1.1的条件,但是奶牛间交换的苹果数小于2才能达到平分的结果, 比如1个苹果
如何分苹果
import java.util.*; public class Main { public static void distributeApple (int cows, ArrayList<Integer> apples) { int appleSum = 0; for (int x: apples) { appleSum+=x; } int average = appleSum/cows; // 分苹果必定失败的第一个判断条件 if (average*cows !=appleSum) { System.out.println(-1); return ; } // 分苹果必定失败的第二个判断条件 for (int x: apples) { if ((x - average)%2 !=0) { System.out.println(-1); return ; } } // 可以成功, 开始分苹果 int count = 0; Collections.sort(apples); while (apples.get(0) != apples.get(apples.size()-1)) { int min = apples.remove(0); int max = apples.remove(apples.size()-1); apples.add(min + 2); apples.add(max - 2); Collections.sort(apples); count++; } System.out.println(count); } public static void main (String args []) { Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { int cows = scanner.nextInt(); scanner.nextLine(); String str = scanner.nextLine(); String [] apples = str.split(" "); ArrayList<Integer> list = new ArrayList(); for (int i=0;i<apples.length;i++) { list.add(Integer.parseInt(apples[i])); } distributeApple(cows,list); } scanner.close(); } }