确定sum之后,找每个nums2中元素对应的最优替换元素(二分法),比较,选出总体最优的。
int minAbsoluteSumDiff(vector<int>& nums1, vector<int>& nums2) {
int len = nums1.size();
int sum = 0;
int t;
vector<int> cur(len);
int max = 0;
for (int i = 0; i < len; i++) {
t = nums2[i];
cur[i] = abs(t - nums1[i]);
sum = (sum+cur[i])%1000000007;
}
sort(nums1.begin(), nums1.end());
for (int i = 0; i < len; i++) {
t = nums2[i];
int l = 0, r = len - 1,mid;
while (l < r) {
mid = (l + r) / 2;
if (t < nums1[mid]) {
r = mid - 1;
}
else if(t>nums1[mid]){
l = mid + 1;
}
else {
l = mid;
break;
}
}
if (cur[i] - abs(t - nums1[l]) > max) {
max = cur[i] - abs(t - nums1[l]);
}
if (l + 1 < len && cur[i] - abs(t - nums1[l + 1]) > max) {
max = cur[i] - abs(t - nums1[l + 1]);
}
if (l - 1 > 0 && cur[i] - abs(t - nums1[l - 1]) > max) {
max = cur[i] - abs(t - nums1[l - 1]);
}
}
sum = (sum - max+ 1000000007) % 1000000007;
return sum;
}
开始没有用二分,直接暴力,然后果然超时了。。。
看了官方题解,发现二分查找可以用一些函数简化:
lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
于是又修改了一下:
int minAbsoluteSumDiff(vector<int>& nums1, vector<int>& nums2) {
int len = nums1.size();
int sum = 0;
int t;
vector<int> cur(len);
int max = 0;
for (int i = 0; i < len; i++) {
t = nums2[i];
cur[i] = abs(t - nums1[i]);
sum = (sum + cur[i]) % 1000000007;
}
sort(nums1.begin(), nums1.end());
for (int i = 0; i < len; i++) {
t = nums2[i];
int k = lower_bound(nums1.begin(), nums1.end(), t) - nums1.begin();
if (k<len && cur[i] - abs(t - nums1[k]) > max) {
max = cur[i] - abs(t - nums1[k]);
}
if (k - 1 >= 0 && cur[i] - abs(t - nums1[k - 1]) > max) {
max = cur[i] - abs(t - nums1[k - 1]);
}
}
sum = (sum - max + 1000000007) % 1000000007;
return sum;
}