一维数组中由n个数,执行加减操作,目标是使n个数中至少有k个数相同,问最少需要多少次才能达到目标。加减操作的规则是:
1)每次对最大的数减1
2)每次对最小的数加1
3)每次只能完成上述两个操作的一个。
题解参考:(先Mark一下,代码还没看懂,以后学完了贪心再回来看看!)
package acm; import java.util.*; public class Main { 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); } }
public class Test { public static void main(String[] args) { // input Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int k = scanner.nextInt(); int[] data = new int[n]; for(int i=0; i<n; i++) { data[i] = scanner.nextInt(); } Arrays.sort(data); // cal result from two paths int res1 = 0; int res2 = 0; for (int i = 0; i < k; i++) { // 若把所有较小高度补到第 k 大的高度,需要的步数 res1 += (data[k-1] - data[i]); // 若把所有较大高度削到倒数第 k 大的高度,需要的步数 res2 += (data[n-1-i] - data[n-1-k+1]); } int index1=k, index2=n-1-k; // 如果第 k 大的高度 h1 在后面的数值中还重复出现了 m 次 // 则说明多进行了 m 次操作 while(index1<n && data[index1++]==data[k-1]) res1--; // 如果倒数第 k 大的高度 h2 在后面的数值中还重复出现了 l 次 // 则说明多进行了 l 次操作 while(index2>=0 && data[index2--]==data[n-1-k+1]) res2--; // 如果 res1 和 res2 中有负值 // 则说明在一开始第 k 大或倒数第 k 大的高度就已经有了 k 个 // 此时返回0 System.out.println(Math.max(0, Math.min(res1, res2))); } }
public class Test { public static void main(String[] args) { Scanner scan=new Scanner(System.in); int N=scan.nextInt(); int k=scan.nextInt(); scan.nextLine(); int [] arr=new int[N]; for(int i=0;i<N;i++){ arr[i]=scan.nextInt(); } Arrays.sort(arr); int result = beginGame(arr, N, k); System.out.println(result); } private static int beginGame(int[] arr, int N, int k) { int path1 = 0; int path2 = 0; for (int i=0;i<k;i++){ path1+=arr[k-1]-arr[i]; path2+=arr[N-i-1]-arr[N-k]; } int index1=k; int index2=N-k-1; while(index1<N&&arr[index1++]==arr[k-1]){ path1--; } while(index2>=0&&arr[index2--]==arr[N-k]){ path2--; } return Math.min(path1, path2); } }
原文:https://www.cnblogs.com/HuangYJ/p/12809514.html