刷最少的题数(蓝桥杯)JAVA

问题描述:

小蓝老师教的编程课有N名学生,编号依次是 1…N。第i号学生这学期

刷题的数量是Ai  。

对于每一名学生,请你计算他至少还要再刷多少道题,才能使得全班刷题

比他多的学生数不超过刷题比他少的学生数。

输入格式 :

第一行包含一个正整数N

第二行包含N个整数:A1 ,A2  ,A3  ,…AN  .

输出格式:

输出N个整数,依次表示第 1…N号学生分别至少还要再刷多少道题。 

样例输入

5

12 10 15 20 6 

样例输出

0 3 0 0 7 

额外样例: 

输入样例1:

3
3 3 3

样例输出1:

0 0 0

 输入样例2:

4
4 3 1 3

输出样例2:

0 0 3 0

 解题思路:

首先,对于本题,我们很容易联想到找到这组数据的中间数。中间数左边的数比它小,中间数右边的数比他大,那显然就需要将数组排序了。

由于中间数的位置非常的特别,接下来我将要分情况对中间数的位置进行分析:

1.当数组的元素个数为奇数个时:

以 1 2 3 4 5来举例(示例一):

中间数的坐标:5/2 = 2对应的元素为3,恰好在数组中间

2.当数组元素个数为偶数个时:

以 1 2 3 4来举例(示例二):

中间数的坐标:4/2 = 2对应元素为3,中间数右边元素比左边元素少1个

再经过一些推理分析很容易得出:中间数组左边元素个数 - 中间元素右边元素个数= 0或1

值得注意的是当取的数在中间数的左边时,中间数左边元素要少一个,再结合上一条的结论很容易分析出取出的数要么等于中间数,要么比中间数大1。

当取出的数比中间数大的话当然就输出零喽。

例如:示例一,二中取1,为了达到题目要求至少还要刷3道题,示例二,为了达到要求还要刷2道题。

这样一般样例就可以解决了。

特殊样例:

1 3  3  4

其中中间数为3,但是与中间数相等地数不止一个,此时再取1的话就不能简单的让再刷题的数量等于3-1了。

这时不妨将两个3都视为中间数,再次统计中间数左边,右边的数量,再和上述一般样例一样根据取数的不同位置进行输出结果,无非就是用了一下整体思想

理论成立代码如下:

import java.util.*;

public class Main {
 public static void main(String[] args) {
   Scanner sc = new Scanner(System.in);
   int n = sc.nextInt();
   int a[] = new int[n];
   int b[] = new int[n];
   for(int i = 0;i < n;i++) {
	 a[i] = sc.nextInt();
	 b[i] = a[i];
   }
   Arrays.sort(b);//对数组b排序
   int middlenumber = b[n/2];//选取中间数
   int left = 0;
   int right = 0;
   for(int i = 0;i < n;i++) {
	 if(i< n/2&&b[i] == middlenumber)//左边部分与中间数相等的
	   left++;
	 else if(i > n/2&&b[i]==middlenumber)//右边部分与中间数相等的
	   right++;
   }
   int L = n/2 - left;//比中间数小的数量
   int R = n - n/2 - right - 1;//比中间数大的数量
   int flag = (R - L) >= 0?1:0;//如果取的数在中间数的左边,那么左边要减去这个数L=L-1
   for(int j = 0;j < n - 1;j++) {
	 if(a[j] < middlenumber)//取的数在左边
	   System.out.print(middlenumber - a[j] + flag + " ");
	 else if(a[j] == middlenumber && R-L > 0)//取的数在中间
	   System.out.print(middlenumber - a[j] + 1 +" ");
	 else//取的数在右边
	   System.out.print(0+" ");
   }
   if(a[n-1] < middlenumber)
	   System.out.print(middlenumber - a[n-1] + flag);
   else if(a[n-1] == middlenumber && R-L > 0)
	 System.out.print(middlenumber - a[n-1] + 1);
   else
	 System.out.print(0);
 }
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值