题目:
小蓝老师教的编程课有 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
评测用例规模与约定
对于 30% 的数据, 1≤N≤1000,0≤Ai≤1000.
对于 100% 的数据, 1≤N≤100000,0≤Ai≤100000.
运行限制
最大运行时间:1s
最大运行内存: 512M
代码:
import java.util.Arrays; import java.util.Scanner; public class zui_shao_shua_ti_shu { public static void main(String[] args) { Scanner sc=new Scanner(System.in); int n,mid; n=sc.nextInt(); int [] arr=new int[n]; int [] a=new int[n]; int [] result=new int[n]; for (int i=0;i<n;i++){ arr[i]=sc.nextInt(); a[i]=arr[i]; } kuaipai(a,0,a.length-1); mid=a[n/2]; int b=0; int c=0; int bigger=0; int smaller=0; for (int i = 0; i < n; i++) { if (arr[i]>mid){ bigger++; } if (arr[i]<mid){ smaller++; } } if (bigger>=smaller){ b=1; } if (bigger>smaller){ c=1; } for (int i=0;i<n;i++){ if (arr[i]<mid){ result[i]=mid+b-arr[i]; }else { if (arr[i] == mid) { result[i] = c; } else { result[i]=0; } } System.out.print(result[i]+" "); } } public static void kuaipai(int [] a,int l,int r){ if (l>=r){ return; } int low=l; int high=r; int pivot=a[l]; while(low<high){ while(a[high]>=pivot&&low<high){ high--; } while(a[low]<=pivot&&low<high){ low++; } if (low<high){ int temp=a[high]; a[high]=a[low]; a[low]=temp; } } a[l]=a[low]; a[low]=pivot; kuaipai(a,l,low-1); kuaipai(a,low+1,r); } }
|
思路:
首先想到的是依靠中间值进行解题,第一次写的代码忽略了中间值可能重复,只通过了3个用例,然后开始改进,这里举几个例子:
3 4 5 6 6 6 7 8 9
如果学生刷题数是这个数组,中间值为6。
其中比6大的有3个比6小的也有3个如果第一个做三道题的学生做到中间值6那么比6小的有2个比6大的有3个不符合要求。刷题数正好是6的同学一道题也不用刷。
3 4 6 6 7 8 9
这个例子比6小的有2个比6大的有3个,所以刷6个题的同学依然要再刷一题才符合要求。
题目中要求比他多的学生数不超过刷题比他少的学生数,那么我们将数组排序中间值肯定是一个分水岭,接下来就需要考虑特殊情况找规律了。
然后呢这道题一开始我用的是Arrays.sort进行排序但发现有三个用例过不去,又尝试了几次发现过不去的三个用例中有几次过去了用时是九百多毫秒,然后就觉得可能程序只是满了几毫秒而导致超时,只要找到一个优化的点应该就能过去了。然后我将排序改成了快排刚好通过
快排虽然写着麻烦些但对计算机来说速度快很多,遇到这种情况的时候很管用,所以快排可以不用但一定要会写。