【贪心算法】[No.126]数组重排最小化差值 | 豆包MarsCode AI 刷题

63 阅读3分钟

题干部分:

问题描述

小C 和小U 有两个数组,分别是 a 和 b,它们的长度相同。小U 想通过重新排列数组 a 的元素,来最小化 a 和 b 之间的差异。具体来说,他们要最小化所有元素差值绝对值之和,即 sum(abs(a[i] - b[i]))
你能帮助小C 和小U 找到这个最小化的值吗?


测试样例

样例1:

输入:a = [2, 1, 3, 2], b = [5, 2, 4, 2]
输出:5

样例2:

输入:a = [1, 4, 6], b = [2, 5, 7]
输出:3

样例3:

输入:a = [1, 9, 6], b = [2, 5, 7]
输出:4

题目分析

若想达到数组差值的最小化,可以优先考虑求数组中每组元素差值绝对值较小值的和。即考虑通过贪心算法对该题目进行求解。由于贪心算法的证明较难,不妨先尝试采取贪心算法的解题策略对该题进行尝试求解。当然,我也会给出自己的证明理解。

题目解答

#include <iostream>
#include <vector>
#include <algorithm>//原题中的string头文件无用,故进行了舍弃

using namespace std;

long long solution(vector<int> a, vector<int> b) {
    sort(a.begin(), a.end());
    sort(b.begin(), b.end());
    
    long long ans = 0;
    for (int i = 0; i < a.size(); ++i) {
        ans += abs(a[i] - b[i]);
    }
    
    return ans;
}

int main() {
    vector<int> a1 = {2, 1, 3, 2}, b1 = {5, 2, 4, 2};
    vector<int> a2 = {1, 4, 6}, b2 = {2, 5, 7};
    vector<int> a3 = {1, 9, 6}, b3 = {2, 5, 7};
    
    cout << (solution(a1, b1) == 5) << endl;
    cout << (solution(a2, b2) == 3) << endl;
    cout << (solution(a3, b3) == 4) << endl;
    
    return 0;
}

提交代码,发现解题成功,该题目使用贪心算法求解是有效的。

算法证明

假设 a 和 b 已经排序,并且 a[i] 和 b[i] 匹配。我们需要证明: sumi=1na[i]b[i]<=sumi=1na[i]b[j]sum_{i=1}^{n} |a[i] - b[i]| <= sum_{i=1}^{n} |a[i] - b[j]|

其中 j 是任意排列。 即证明,表示在数组 a 和 b 已经排序的情况下,按顺序匹配 a[i] 和 b[i] 的差值总和小于等于任何其他匹配方式的差值总和。

具体证明步骤

  1. 排序的必要性

    • 假设我们不对数组 a 和 b 进行排序,而是直接计算差值。由于 abs(a[i] - b[i]) 的值取决于 a[i] 和 b[i] 的相对大小,如果不排序,可能会出现某些 a[i] 和 b[i] 的差值较大的情况,从而导致总差值较大。
    • 通过排序,我们可以确保 a[i] 和 b[i] 在相对大小上尽可能接近,从而最小化差值。
  2. 贪心选择性质

    • 假设我们有一个最优解,其中 a 和 b 的元素没有按顺序匹配。我们可以通过交换 a 和 b 中的元素,使得 a[i] 和 b[i] 的差值更小。
    • 具体来说,假设 a 和 b 已经排序,但 a[i] 和 b[j] 匹配,其中 i != j。我们可以通过交换 a[i] 和 a[j] 或 b[i] 和 b[j],使得 a[i] 和 b[i] 匹配,从而减少差值。
  3. 最优子结构性质

    • 假设我们已经对 a 和 b 进行了排序,并且按顺序匹配它们。对于每个 ia[i] 和 b[i] 的差值是独立的,不会影响其他 a[j] 和 b[j] 的差值。
    • 因此,通过按顺序匹配 a 和 b,我们可以确保每个 a[i] 和 b[i] 的差值最小,从而使得总差值最小。

至此,我们成功证明了贪心算法的正确性。

题目总结

当我们在解题过程中遇到一些疑似使用贪心算法求解,且自己对其他解法毫无思路的题目时,不妨使用贪心算法进行尝试,或许你的直觉就是正确的。