贪心的思想,同时其他答案里给的bug测试用例也可以通过
package acm; import java.util.*; public class Main3 { public static void main(String[] args) { Scanner sc=new Scanner(System.in); int n=sc.nextInt(),k=sc.nextInt(); int sum=0; int[] data=new int[n]; for(int i=0;i<n;i++){ data[i]=sc.nextInt(); sum+=data[i]; } Arrays.sort(data); int p=-1; int ans=Integer.MAX_VALUE; int pre=0; //最终的结果肯定是要有某个数出现的个数>=k,把这个数叫做基准数 for(int i=0;i<n;){ p=i; while(p<n&&data[p]==data[i]){ sum-=data[i]; p++; } int ned=Math.max(0,k-p+i); //ned的含义是目前如果让data[i]作为基准数,还差多少个达到k,如果为0说明已经超过k个了,也就是说不需要任何操作就可以满足题意要求 if(ned==0){ ans=0; // break; } if(p>=k){//p>=k说明以data[i]为基准数,调整下标i之前的数到达基准数,就可以满足题意,求出这时候需要操作个数 ans=Math.min(ans,i*data[i]-pre-(i-ned));//pre记录的是下标i之前的所有数字之和,要把下标i之前的数调整到等于基准数data[i],操作次数=i*data[i]-pre //同时要考虑只需要k个满足就可以了,也就是这时候可以有i-ned不满足,也就是i-ned个数可以调整等于data[i]-1,所以要减去i-ned. } if(n-i>=k){//i往后的数字降到data[i]就直接可以满足题意,与p>=k类似,只是调整方向不一样 ans=Math.min(ans,sum-(n-p)*data[i]-(n-p-ned));// } ans=Math.min(ans,i*data[i]-pre+sum-(n-p)*data[i]-(n-(p-i)-ned));//同时需要判断两边都做操作的情况下调整的个数 pre+=data[i]*(p-i);//pre加上data[i]乘以data[i]的个数,那么下一步i=p的时候pre就代表i之前所有数之和。 i=p; } System.out.println(ans); } }