给定一个数组 nums,其中有 n 个非负整数。你的目的是进行两次操作,使得数组的元素之和最小。
每次操作形如:任选一个整数 x ,将数组中所有大于等于 x 的数减去 x 。
[2,1,3]
0
初始数组为 [2, 1, 3]。先选择 x = 2,则所有大于等于 2 的元素减去 2 ,变成 [0, 1, 1]。再选择 x = 1,则所有大于等于 1 的元素减去 1 ,变成 [0, 0, 0]。所以数组元素之和的最小值为 0。
对于所有的测试数据,保证有且
。
public long minimumValueAfterDispel (int[] nums) { // write code here Arrays.sort(nums); long sum = 0;//记录整个数组的和 long max = 0;//记录能够减去的最大值 for(int j=0;j<nums.length;j++){ sum += nums[j]; int index1 = j; int index2 = j; int index3 = j; for(int i=0;i<=j;i++){ while(index1 > 0 && nums[index1-1] >= nums[j]-nums[i]){ index1--; } while(index2 > i && nums[index2-1] >= nums[j]-nums[i]){ index2--; } while(index3 < nums.length && (long)nums[index3] < (long)nums[i]+nums[j]){ index3++; } /* 假设两次减去的数为a,b(a<b)总共分为三种情况 1.a=nums[j]-nums[i] b=nums[i] 2.a=nums[i] b=nums[j]-nums[i] 3.a=nums[i] b=nums[j] 分段函数的边界: 1. index1 < i < j < nums.length 其实index1大于i时不碍事 i-index1变成负数不会影响max的计算 2. i < index2 < j < nums.length 3. i < j < index3 < nums.length 对于第一种情况 index1到i之间的数只能减去a 即 nums[j]-nums[i], i到j之间的数只能减去b 即nums[i] , j到最后的数可以减去a+b 即nums[j] 对于第二种情况 i到index2之间的数只能减去a 即 nums[i], index2到j之间的数只能减去b 即nums[j]-nums[i] , j到最后的数可以减去a+b 即nums[j] 对于第三种情况 i到j之间的数只能减去a 即 nums[i], j到index3之间的数只能减去b 即nums[j], index3到最后的数可以减去a+b 即nums[j]+nums[i] 另外一个答案的版本之所以跟这个不一样是因为他给表达式化简了....... */ long tmp1 = (i-index1)*((long)nums[j]-nums[i]) + (j-i)*(long)nums[i] + (nums.length-j)*(long)nums[j]; long tmp2 = (index2-i)*((long)nums[i]) + (j-index2)*((long)nums[j]-nums[i]) + (nums.length-j)*(long)nums[j]; long tmp3 = (j-i)*(long)nums[i] + (index3-j)*(long)nums[j] + (nums.length-index3)*((long)nums[i]+nums[j]); max = Math.max(max,tmp1); max = Math.max(max,tmp2); max = Math.max(max,tmp3); } } return sum - max; }
import java.util.*; public class Solution { /** * 返回两次操作后,数组元素之和的最小值 * @param nums int整型一维数组 这你你需要操作的数组 * @return long长整型 */ public long minimumValueAfterDispel (int[] nums) { doFun(nums); doFun(nums); int sum = 0; for(int i=0;i<nums.length;i++){ sum += nums[i]; } return sum; } private void doFun(int[] nums){ int n = nums.length; Arrays.sort(nums); long max = 0; int index = 0; for(int i=index;i<n;i++){ long tempMax = nums[i] * (n-i); if(max<tempMax){ index = i; max = tempMax; } } int value = nums[index]; for(int i=index;i<n;i++){ nums[i] -= value; } } public static void main(String[] args) { Solution solution = new Solution(); int[] arr = new int[] {604, 349, 741, 143, 667, 997, 255, 653, 720, 631, 611, 574, 770, 125, 419, 292, 311, 756, 702, 816, 122, 602, 813, 551, 698, 764, 839, 531, 40, 239, 907, 841, 378, 710, 964, 34, 666, 864, 791, 166, 341, 987, 749, 700, 185, 96, 236, 471, 31, 569, 290, 398, 481, 472, 37, 496, 818, 393, 267, 528, 942, 429, 570, 52, 237, 80, 120, 236, 421, 8, 320, 901, 257, 767, 603, 903, 666, 373, 673, 561, 507, 736, 786, 401, 994, 746, 287, 874, 505, 516, 749, 514, 413, 883, 868, 865, 184, 19, 309, 912, 236, 827, 292, 452, 434, 32, 25, 972, 762, 123, 614, 767, 301, 812, 917, 967, 429, 921, 12, 855, 717, 965, 781, 377, 909, 492, 906, 265, 478, 538, 401, 203, 222, 418, 247, 982, 715, 168, 779, 681, 73, 507, 222, 274, 834, 330, 799, 324, 407, 310, 650, 909, 732, 540, 687, 128, 557, 883, 281, 392, 140, 103, 736, 302, 482, 711, 663, 776, 316, 460, 33, 785, 728, 686, 450, 981, 968, 729, 829, 587, 409, 305, 881, 192, 974, 370, 82, 262, 763, 132, 831, 390, 180, 541, 404, 758, 920, 607, 252, 614, 214, 51, 676, 802, 387, 430, 566, 978, 962, 147, 120, 489, 422, 118, 285, 783, 512, 548, 922, 547, 346, 530, 204, 433, 10, 145, 456, 606, 481, 410, 686, 23, 326, 834, 421, 611, 434, 432, 137, 926, 74, 64, 637, 282, 283, 316, 70, 957, 113, 919, 282, 414, 280, 992, 785, 815, 720, 343, 967, 304, 248, 204, 815, 952, 796, 205, 874, 638, 663, 404, 62, 690, 921, 317, 848, 856, 409, 651, 856, 953, 241, 376, 175, 103, 804, 28, 985, 395, 569, 390, 481, 639, 260, 565, 43, 959, 107, 18, 883, 577, 477, 197, 929, 632, 855, 789, 378, 51, 977, 489, 24, 487, 94, 922, 956, 498, 571, 191, 170, 157, 134, 129, 753, 812, 875, 592, 930, 458, 361, 534, 649, 890, 62, 590, 151, 437, 685, 93, 374, 97, 348, 759, 442, 336, 646, 736, 875, 462, 486, 485, 874, 964, 270, 655, 781, 450, 281, 413, 905, 637, 350, 33, 976, 785, 378, 206, 333, 607, 603, 683, 264, 513, 534, 769, 915, 256, 754, 448, 178, 808, 8, 958, 745, 745, 626, 771, 661, 825, 796, 394, 724, 38, 867, 730, 609, 212, 531, 850, 665, 27, 56, 180, 322, 11, 795, 375, 868, 319, 477, 681, 174, 962, 20, 823, 436, 499, 638, 816, 876, 45, 794, 234, 849, 634, 600, 408, 779, 955, 22, 439, 155, 679, 638, 187, 860, 560, 882, 369, 317, 186, 952, 0, 893, 90, 359, 4, 130, 515, 796, 334, 190, 501, 990, 17, 391, 935, 523, 992, 215, 977, 434, 322, 97, 349, 580, 430, 591, 79, 231, 650, 98, 464, 181, 658, 354, 198, 764, 866, 440, 795, 72, 153, 690, 520, 763, 515, 195, 39, 871, 782, 492, 184, 127, 188, 557, 494, 375, 167, 317, 921, 739, 385, 699, 355, 649, 750, 83, 849, 913, 850, 810, 317, 741, 11, 573, 674, 425, 293, 816, 548, 747, 177, 290, 75, 723, 33, 748, 797, 618, 323, 696, 920, 915, 788, 537, 510, 351, 631, 422, 187, 602, 789, 128, 629, 151, 621, 708, 683, 530, 176, 88, 986, 392, 391, 784, 32, 693, 561, 282, 27, 564, 331, 812, 798, 858, 239, 278, 970, 983, 292, 896, 882, 456, 972, 366, 14, 761, 152, 639, 443, 944, 117, 73, 929, 44, 193, 186, 915, 310, 39, 36, 935, 272, 195, 807, 561, 600, 811, 80, 607, 147, 200, 186, 649, 676, 76, 86, 283, 847, 740, 573, 671, 750, 615, 881, 609, 969, 73, 938, 968, 216, 144, 793, 827, 178, 229, 160, 737, 506, 713, 619, 509, 23, 422, 236, 73, 954, 710, 647, 740, 668, 767, 971, 940, 763, 573, 722, 997, 652, 8, 525, 762, 549, 761, 770, 440, 608, 784, 997, 696, 448, 72, 98, 889, 278, 898, 477, 216, 703, 159, 856, 957, 670, 933, 121, 339, 127, 439, 145, 525, 453, 384, 529, 695, 952, 134, 478, 12, 793, 932, 288, 829, 259, 35, 724, 842, 661, 43, 473, 87, 745, 630, 127, 585, 923, 456, 953, 665, 862, 581, 370, 78, 504, 513, 612, 749, 424, 512, 367, 953, 53, 678, 642, 975, 939, 104, 781, 259, 386, 838, 654, 43, 562, 776, 798, 494, 54, 50, 536, 950, 441, 860, 544, 886, 563, 592, 656, 459, 148, 816, 910, 208, 949, 816, 694, 189, 831, 998, 690, 826, 590, 217, 695, 522, 373, 878, 71, 75, 889, 681, 191, 817, 671, 280, 439, 677, 49, 456, 395, 747, 529, 127, 600, 400, 623, 541, 978, 14, 461, 790, 94, 957, 577, 212, 189, 928, 372, 227, 440, 424, 534, 946, 224, 801, 936, 102, 462, 860, 127, 93, 364, 747, 239, 972, 205, 416, 30, 652, 55, 770, 768, 799, 751, 476, 315, 801, 832, 624, 400, 386, 363, 988, 519, 311, 899, 241, 575, 128, 77, 881, 740, 645, 78, 97, 498, 930, 801, 607, 102, 972, 343, 584, 428, 982, 595, 634, 717, 48, 557, 936, 311, 803, 415, 55, 178, 856, 444, 992, 469, 705, 265, 646, 712, 526, 546, 479, 958, 593, 387, 622, 816, 12, 5, 915, 882, 216, 237, 372, 788, 842, 318, 676, 471, 609, 806, 905, 39, 640, 595, 931, 884, 564, 239, 988, 683, 563, 393, 284, 481, 605, 753, 373, 125, 115, 850, 94, 818, 787, 364, 151, 45, 303, 309, 129, 517, 266, 148, 261, 609, 219, 395, 51, 600, 800, 814, 355, 779, 189, 118, 617, 126, 52, 819, 62, 394, 899, 907, 347, 103, 246, 477, 957, 199, 881, 270, 844, 910, 122, 54, 385, 670, 641, 570, 383, 725, 539, 156, 143, 394, 897, 857, 202, 913, 41, 252, 214, 816, 635, 962, 290, 234, 242, 478, 101, 474, 967, 249, 176, 670, 441, 836, 353, 653, 285, 396, 16, 130, 924, 324, 876}; System.out.println(solution.minimumValueAfterDispel(arr)); } }
\
long long minimumValueAfterDispel(vector<int> nums) { // write code here sort(nums.begin(), nums.end()); long long sum = 0; for(auto i:nums){ sum += i; } long max_1 = 0; long index_1 = 0; for(int i=0;i<nums.size();i++){ long long temp = (nums.size() - i)*nums[i]; if(temp>max_1){ max_1 = temp; index_1 = i; } } long long temp = nums[index_1]; for(int i=index_1;i<nums.size();i++){ nums[i] = nums[i] - temp; } sort(nums.begin(), nums.end()); long long max_2 = 0; for(int i=0;i<nums.size();i++){ long long temp_2 = (nums.size() - i)*nums[i]; max_2 = max(max_2, temp_2); } return sum - max_1 - max_2; }感觉思路完全没问题, 感觉测试用例有问题
typedef long long ll; class Solution { public: long long minimumValueAfterDispel(vector<int>& nums) { // write code here ll ans = 0; ll sum = 0; for(auto v : nums) sum += v; sort(nums.begin(), nums.end()); ll n = nums.size(); vector<int> tmp(n,0); for(int i = 0;i < n; i ++) { //a = nums[i] , b= tmp[j] if(i == 0 || nums[i] != nums[i-1]){ int cnt = 0; int k1 = 0,k2 = i; while(k1 < i && k2 < n) { if(nums[k1] < nums[k2] - nums[i]) tmp[cnt ++] = nums[k1 ++]; else tmp[cnt ++] = nums[k2++] - nums[i]; } while(k1 < i) tmp[cnt ++] = nums[k1 ++]; while(k2 < n) tmp[cnt ++] = nums[k2++] - nums[i]; for(int j = 0; j < n; j ++) { if(j == 0||tmp[j] != tmp[j-1]){ ans = max(ans,1LL*nums[i] * (n-i) + 1LL*tmp[j]*(n-j)); } } } } for(int i = 0;i < n; i ++) { //a = nums[j] - nums[i] > nums[i], b = nums[i] if(i == 0 || nums[i] != nums[i-1]) { int index = i + 1; for(int j = i + 1;j < n; j ++) { if(nums[j] != nums[j-1] && nums[j] - nums[i] > nums[i]) { while(nums[index] < nums[j] - nums[i]) index ++; ans = max(ans,(n-j)*1LL*nums[j] + (j-index)*1LL*(nums[j]-nums[i]) + (index-i)*1LL*nums[i]); } } } } return sum - ans; } };
public static long minimumValueAfterDispel(int[] nums) { // write code here Arrays.sort(nums);//顺序排列,当减去面积相同时取最小的h long sum = 0;//总面积 for (int i = 0; i < nums.length; i++) { sum += nums[i]; } // System.out.println("总面积:"+sum); Integer[] integers = new Integer[nums.length]; for (int i = 0; i < nums.length; i++) { integers[i] = nums[i]; } List<Integer> f = Arrays.asList(integers);//方便修改数据 for (int i = 0; i < 2; i++) {//两次操作 long c = 0;//减去的面积 long e = 0;//结束该次操作之后的h for (Integer j : f) { long h = j;//给高赋值 long l = 0;//长 for (Integer k : f) { if (k >= h) { l++; } } long d = h * l; if (c < d && d <= sum) {//获取最大的减去面积并且该面积小于等于当前总面积 e = h; c = d; } } //结束该次操作之后对list进行处理 // System.out.println("第"+(i+1)+"次减去面积的高度:" + e); for (int m = 0;m<f.size();m++) { if (f.get(m) >= e) {//将数组中所有大于等于 x 的数减去 x f.set(m,(int) (f.get(m) - e)); } } // System.out.println("第"+(i+1)+"次减去的面积:" + c); sum = sum - c; } return sum; }
public long minimumValueAfterDispel (int[] nums) { // write code here long sum = 0; for(int i:nums){ sum += i; } int[] nums2 = new int[nums.length]; for(int i=0;i<nums.length;i++){ nums2[i] = nums[i]; } sum -= countMax(nums, nums2); return sum; } public int countMax(int[] nums, int[] nums2){ Arrays.sort(nums); int max = 0; int n = nums.length; for(int i=0;i<n;i++){ // 第一次减少的值 int dele1 = nums[i]*(n-i); int n1 = nums[i]; for(int d=i;d<n;d++){ nums2[d] -= n1; } Arrays.sort(nums2); for(int j=0;j<n;j++){ // 第二次减少的值 int dele2 = nums2[j]*(n-j); if((dele1+dele2)>max){ // 获取两次能够减少的最大值 max = dele1+dele2; } } // 复原为减少之前的值 for(int d=0;d<n;d++){ nums2[d] = nums[d]; } } return max; }
public long minimumValueAfterDispel (int[] nums) { // write code here nums=findPosition(nums); nums=findPosition(nums); int minValue=0; for (int i = 0; i < nums.length; i++) { minValue=minValue+nums[i]; } System.out.println("minValue: "+minValue); return minValue; } public int[] findPosition(int[] nums){ int max=0; int value=0; Arrays.sort(nums); for (int i = 0; i <nums.length ; i++) { int n=nums[i]; int reduce=n*(nums.length-i); if (max<reduce){ max=reduce; value=n; } } for (int i = 0; i <nums.length ; i++){ if (nums[i]>=value) { nums[i] = nums[i] - value; } } return nums; }
class Solution { public: /** * 返回两次操作后,数组元素之和的最小值 * @param nums int整型vector 这你你需要操作的数组 * @return long长整型 */ long long minimumValueAfterDispel(vector<int>& nums) { // write code here // write code here long ans=0,sum=0; int n=nums.size(); //System.out.println(n); for(int i=0;i<n;i++) sum+=nums[i]; ans=sum; sort(nums.begin(),nums.end()); for(int i=n-1;i>0;i--){ if(i<n-1 && nums[i]==nums[i+1]) continue; for(int j=i;j>=0;j--){ if(j<n-1 && nums[j]==nums[j+1]) continue; long long add=nums[i]+nums[j]; long long sub=nums[i]-nums[j]; long long xx=nums[i],yy=nums[j]; int q=lower_bound(nums.begin(),nums.end(),add)-nums.begin(); int p=lower_bound(nums.begin(),nums.end(),sub)-nums.begin(); ans=min(ans,sum-(n-q)*add-(q-i)*xx-(i-j)*yy); if(p<=j) ans=min(ans,sum-(n-i)*xx-(i-j)*yy-(j-p)*sub); else ans=min(ans,sum-(n-i)*xx-(i-p)*sub-(p-j)*yy); } } return ans; } long long min(long long x,long long y){ return x>y?y:x; } };
long long minimumValueAfterDispel(vector<int>& nums) { int n = nums.size(); sort(nums.begin(), nums.end()); long long sum = 0; for (int i = 0; i < n; ++ i) sum += nums[i]; long long min1 = INT_MAX; int target = -1; int index = -1; for (int i = 0; i < n; ++ i) { if (min1 > (sum - (n - i) * nums[i]) ) { min1 = sum - (n - i) * nums[i]; index = i; target = nums[i]; } } for (int i = index; i < n; ++ i) { nums[i] -= target; } sort(nums.begin(), nums.end()); long long min2 = INT_MAX; for (int i = 0; i < n; ++ i) { min2 = min(min2, min1 - (n - i) * nums[i]); } return min2; }
import java.util.*; public class Solution { /** * 返回两次操作后,数组元素之和的最小值 * @param nums int整型一维数组 这你你需要操作的数组 * @return long长整型 */ public long minimumValueAfterDispel (int[] nums) { // write code here long a=0; long max; //要减去的最大值 long cur; //要减去的当前值 long count; //数组中大于等于该元素值的元素个数 long total; //当前数组的元素总和 long num; //保存取最大值时,当前数组中所选取的元素 for(int k=0;k<2;k++){ //操作两次 Arrays.sort(nums); max = 0; cur =0; count =0; total = 0; num = 0; for(int i =0;i<nums.length;i++){ //遍历数组 for(int j=0;j<nums.length;j++){ //再次遍历数组,统计数组中大于等于该元素值的元素个数 if(nums[j]>=nums[i]){ count++; } } cur = nums[i]*count; //记录要减去的当前值 count = 0; if(cur>max){ //比较当前值与最大值 max = cur; num = nums[i]; //保存取最大值时,当前数组中所选取的元素 } total += nums[i]; //当前数组的元素总和 } a = total - max; //计算数组元素之和的最小值 for(int i =0;i<nums.length;i++){ //根据保存的num,生成第1次操作后的数组 if(nums[i]>=num){ nums[i]-= num; } } } return a; } }
import java.util.*; public class Solution { /** * 返回两次操作后,数组元素之和的最小值 * @param nums int整型一维数组 这你你需要操作的数组 * @return long长整型 */ public long minimumValueAfterDispel (int[] nums) { // write code here int max_1=nums[0]; int max_3; int max_2; int max_4; long sums=0; int nums_length=nums.length; long min=Long.MAX_VALUE; int[] nums_1=new int[nums_length]; int[] nums_2=new int[nums_length]; for (int i=1;i<nums_length;i++) { if(max_1<nums[i]) { max_1=nums[i]; } } // int max_2=(int)(max_1/2)+1; max_2=max_1; for (int i=1;i<=max_2;i++) { for (int j=0;j<nums_length;j++) { if(nums[j]>=i) { nums_1[j]=nums[j]-i; }else { nums_1[j]=nums[j]; } } max_3=nums_1[0]; for (int k=1;k<nums_length;k++) { if(max_3<nums_1[k]) { max_3=nums_1[k]; } } //int max_4=(int)(max_3/2)+1; max_4=max_3; for (int m=1;m<=max_4;m++) { sums=0; for (int j=0;j<nums_length;j++) { if(nums_1[j]>=m) { nums_2[j]=nums_1[j]-m; }else { nums_2[j]=nums_1[j]; } sums=sums+nums_2[j]; } if(sums<min) { min=sums; } } } return min; } }