1 題目描述
題目連結:https://leetcode-cn.com/problems/minimum-absolute-sum-difference/添加連結描述
給你兩個正整數數組 nums1 和 nums2 ,數組的長度都是 n 。
數組 nums1 和 nums2 的 絕對內插補點和 定義為所有 |nums1[i] - nums2[i]|(0 <= i < n)的 總和(下标從 0 開始)。
你可以選用 nums1 中的 任意一個 元素來替換 nums1 中的 至多 一個元素,以 最小化 絕對內插補點和。
在替換數組 nums1 中最多一個元素 之後 ,傳回最小絕對內插補點和。因為答案可能很大,是以需要對 109 + 7 取餘 後傳回。
|x| 定義為:
如果 x >= 0 ,值為 x ,或者
如果 x <= 0 ,值為 -x
示例 1:
輸入:nums1 = [1,7,5], nums2 = [2,3,5]
輸出:3
解釋:有兩種可能的最優方案:
- 将第二個元素替換為第一個元素:[1,7,5] => [1,1,5] ,或者
-
将第二個元素替換為第三個元素:[1,7,5] => [1,5,5]
兩種方案的絕對內插補點和都是 |1-2| + (|1-3| 或者 |5-3|) + |5-5| = 3
示例 2:
輸入:nums1 = [2,4,6,8,10], nums2 = [2,4,6,8,10]
輸出:0
解釋:nums1 和 nums2 相等,是以不用替換元素。絕對內插補點和為 0
示例 3:
輸入:nums1 = [1,10,4,4,2,7], nums2 = [9,3,5,1,7,4]
輸出:20
解釋:将第一個元素替換為第二個元素:[1,10,4,4,2,7] => [10,10,4,4,2,7]
絕對內插補點和為 |10-9| + |10-3| + |4-5| + |4-1| + |2-7| + |7-4| = 20
2 代碼/C++
class Solution {
public:
static constexpr int mod = 1'000'000'007; // constexpr定義編譯器常量,大數可以用逗号隔開
int minAbsoluteSumDiff(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size();
vector<int>rec(nums1); // vector的定義初始化,複制另外一個vector
int maxn = 0, s = 0;
sort(rec.begin(), rec.end()); // 排序,從小到大
for (int i=0; i<n; ++i){
int diff = abs(nums1[i] - nums2[i]);
s = (s + diff) % mod;
// lower_bound 采用二分法尋找第一個大于等于target的數的位置,不存在則傳回end,減begin得到其在數組下标
// upper_bound 采用二分法尋找第一個小于等于target的數的位置,不存在則傳回end,減begin得到其在數組下标
int j = lower_bound(rec.begin(), rec.end(), nums2[i]) - rec.begin();
if (j<n){
// 第一個大于等于nums2[i]的數
// 如果j是0,則表示rec中的數都大于等于target,傳回最小的數,也就是下标0
maxn = max(maxn, diff - (rec[j] - nums2[i]));
}
if (j>0){
// 最後一個小于nums2[i]的數
// 如果j是n,則表示rec中的數都小于target,傳回最大的數,也就是下标n-1
maxn = max(maxn, diff - (nums2[i] - rec[j-1]));
}
}
return (s - maxn + mod) % mod; // 防止s-maxn<mod
}
};