You are given two integer arrays nums1
and nums2
, both of length n
. The absolute sum difference of these arrays is defined as the sum of |nums1[i] - nums2[i]|
for all valid indices i
(from 0
to n-1
).
You are allowed to replace at most one element in nums1
with any other element from nums1
(i.e., you can swap one value in nums1
with any other value from nums1
, possibly itself).
Your goal is to minimize the absolute sum difference after performing at most one such replacement. Return the minimum possible absolute sum difference modulo 10^9 + 7
.
105
elements.105
.nums2
to replace elements in nums1
.The problem asks us to minimize the total difference between two arrays by changing at most one element in the first array. A brute-force approach would be to try every possible replacement for every position, but with large arrays, this would be too slow.
Instead, we realize that for each index i
, we want to see if we can replace nums1[i]
with another value from nums1
to make nums1[i]
as close as possible to nums2[i]
. If we can make nums1[i]
equal to nums2[i]
, the difference at that position becomes zero, which is optimal.
To do this efficiently, we need a way to quickly find, for each nums2[i]
, the value in nums1
that is closest to it. This suggests using binary search on a sorted copy of nums1
.
|nums1[i] - nums2[i]|
for all indices.
nums1
to allow fast binary search for the closest value to any nums2[i]
.
i
:
nums1
that is closest to nums2[i]
.nums1[i]
were replaced by this closest value.10^9 + 7
.
We use a sorted array and binary search because searching for the closest value in an unsorted array would be too slow (O(n) per query), but with sorting, we can do it in O(log n) per query.
Input: nums1 = [1,7,5]
, nums2 = [2,3,5]
nums1
: [1,5,7]nums1
(O(n^2)), which is not feasible for large n.
nums1
: O(n log n)
The key insight is to recognize that replacing a value in nums1
with the value closest to nums2[i]
can minimize the absolute difference at that index. By pre-sorting nums1
, we can efficiently find the closest value using binary search, allowing us to compute the optimal replacement in O(n log n) time. This approach balances correctness and performance, making it suitable for large input sizes.
import bisect
class Solution:
def minAbsoluteSumDiff(self, nums1, nums2):
MOD = 10 ** 9 + 7
n = len(nums1)
sorted_nums1 = sorted(nums1)
total = 0
max_gain = 0
for i in range(n):
a, b = nums1[i], nums2[i]
diff = abs(a - b)
total += diff
idx = bisect.bisect_left(sorted_nums1, b)
# Try the closest value on the left
if idx > 0:
gain = diff - abs(sorted_nums1[idx-1] - b)
if gain > max_gain:
max_gain = gain
# Try the closest value on the right
if idx < n:
gain = diff - abs(sorted_nums1[idx] - b)
if gain > max_gain:
max_gain = gain
return (total - max_gain) % MOD
#include <vector>
#include <algorithm>
#include <cstdlib>
using namespace std;
class Solution {
public:
int minAbsoluteSumDiff(vector<int>& nums1, vector<int>& nums2) {
const int MOD = 1e9 + 7;
int n = nums1.size();
vector<int> sorted_nums1(nums1);
sort(sorted_nums1.begin(), sorted_nums1.end());
long total = 0, max_gain = 0;
for (int i = 0; i < n; ++i) {
int a = nums1[i], b = nums2[i];
int diff = abs(a - b);
total += diff;
auto it = lower_bound(sorted_nums1.begin(), sorted_nums1.end(), b);
if (it != sorted_nums1.begin()) {
max_gain = max(max_gain, (long)diff - abs(*(it - 1) - b));
}
if (it != sorted_nums1.end()) {
max_gain = max(max_gain, (long)diff - abs(*it - b));
}
}
return (total - max_gain + MOD) % MOD;
}
};
import java.util.*;
class Solution {
public int minAbsoluteSumDiff(int[] nums1, int[] nums2) {
int MOD = 1_000_000_007;
int n = nums1.length;
int[] sorted = nums1.clone();
Arrays.sort(sorted);
long total = 0, maxGain = 0;
for (int i = 0; i < n; ++i) {
int a = nums1[i], b = nums2[i];
int diff = Math.abs(a - b);
total += diff;
int idx = Arrays.binarySearch(sorted, b);
if (idx < 0) idx = -idx - 1;
if (idx > 0) {
maxGain = Math.max(maxGain, diff - Math.abs(sorted[idx - 1] - b));
}
if (idx < n) {
maxGain = Math.max(maxGain, diff - Math.abs(sorted[idx] - b));
}
}
return (int)((total - maxGain + MOD) % MOD);
}
}
var minAbsoluteSumDiff = function(nums1, nums2) {
const MOD = 1e9 + 7;
const n = nums1.length;
let sorted = nums1.slice().sort((a, b) => a - b);
let total = 0;
let maxGain = 0;
for (let i = 0; i < n; ++i) {
let a = nums1[i], b = nums2[i];
let diff = Math.abs(a - b);
total += diff;
// Binary search for closest value in sorted
let left = 0, right = n - 1;
while (left < right) {
let mid = Math.floor((left + right) / 2);
if (sorted[mid] < b) left = mid + 1;
else right = mid;
}
// Check left and left-1
if (left > 0) {
maxGain = Math.max(maxGain, diff - Math.abs(sorted[left - 1] - b));
}
if (left < n) {
maxGain = Math.max(maxGain, diff - Math.abs(sorted[left] - b));
}
}
return (total - maxGain + MOD) % MOD;
};