绝对和差值:二分与贪心思想的联合考察

Posted C_YCBX Py_YYDS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了绝对和差值:二分与贪心思想的联合考察相关的知识,希望对你有一定的参考价值。

题目

在这里插入图片描述
oj平台

题目解析

最开始读完题,我还得意洋洋的以为,只需要找到,不改变情况下,绝对值差值最大的那个,然后对他进行差值最小的优化。。。
还是太年轻了,这样的贪心完全不对,我们将每一个绝对值差值和他的最优情况的差值进行比较,得出这两个差值的最大值,而不是单纯只考虑到原绝对值差值大。。。

  • 错误代码示范
class Solution {
public:
const int MOD = 1e9+7;
    int minAbsoluteSumDiff(vector<int>& nums1, vector<int>& nums2) {
        int sz = nums1.size();
        vector<int>tt(sz);
        for(int i=0;i<sz;i++)
            tt[i] = abs(nums1[i]-nums2[i]);
        int max = INT_MIN,pos;
        int res = 0;
        //寻找误差差值最大的数,以及它对应的位置(要改肯定也就是改这个数最好)
        for(int i=0;i<sz;i++){
            if(tt[i]>max){
                max = tt[i];
                pos = i;
            }
            res += tt[i];
        }
        //由于只需要前面的序号对应即可,所以这里能排序查找替换的最佳值
        sort(nums1.begin(),nums1.end());
        //可以通过二分确定修改为哪个数最好,先选中大于或等于nums2[pos]的第一个值
        int p;
        int l = 0,r = sz;
        while(l<r){
            int mid = l+(r-l)/2;
            if(nums1[mid]>=nums2[pos])
                r = mid;
            else{
                l = mid+1;
            }
        }
    if(l==sz){
        p = abs(nums1[l-1]-nums2[pos]);
    }else{
        if(nums1[l]==nums2[pos]||l==0)
            p = nums2[pos] - nums1[l];
        else{
            p = min(abs(nums2[pos]-nums1[l]),abs(nums2[pos]-nums1[l-1]));
        }
    }
        res = (res - max+p)%MOD;
        
        return res;
    }
};
  • 正确做法与思路:
  1. 我们通过原先的 diff-opt_diff 的方式来寻找那个最需要替换绝对值!!!
  2. 那么 opt_diff 如何求呢?可以通过二分查找找等于 nums2[i] 的左边界来寻找每个绝对值的最优解 opt_diff ,找到左边界i后,可以根据i的值分情况得到最优解.
  3. 三种情况:1.i == 0 2.i==n 3.0<i<n.这三种特殊情况都可以用两类if分流讨论:如果 i<nrec[i] - nums2[i] 一定 >=0 ,如果 i>0 ,则 nums2[i]-resc[i-1] 一定 >=0 ,这使得无论是两种特殊情况还是不特殊的情况,都将被考虑到!
  4. 关于模运算细节:模运算的分步过程中,如果出现某步使得 (x)%mod 中的x符号发生改变,那么这个模运算的分步过程将不再准确,可以在其中添加k倍的mod使得x符号不发生改变,从而最终的模运算结果不会出差错。此题由于最后出现了减法,可能会对括号中的正负产生影响,所以直接再加上一个mod,而无论是否改变符号加上mod都不会改变最终的模值。

解题代码

class Solution {
public:
    const int mod = 1e9+7;

    int minAbsoluteSumDiff(vector<int>& nums1, vector<int>& nums2) {
        //用于二分查找最优绝对值差值的备胎
        vector<int> rec(nums1);
        sort(rec.begin(), rec.end());
        int sum = 0, maxn = 0;
        int n = nums1.size();
        for (int i = 0; i < n; i++) {
            int diff = abs(nums1[i] - nums2[i]);
            sum = (sum + diff) % mod;
            //二分寻找左边界的函数
            int j = lower_bound(rec.begin(), rec.end(), nums2[i]) - rec.begin();
            if (j < n) {
                maxn = max(maxn, diff - (rec[j] - nums2[i]));
            }
            if (j > 0) {
                maxn = max(maxn, diff - (nums2[i] - rec[j - 1]));
            }
        }
        //注意加上mod
        return (sum - maxn +mod) % mod;
    }
};

以上是关于绝对和差值:二分与贪心思想的联合考察的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 1818 绝对差值和[数学] HERODING的LeetCode之路

二分数组差值最大

Educational Round 64 C. Match Points(二分,贪心)

Educational Round 64 C. Match Points(二分,贪心)

Kattis - icpccamp ICPC Camp(二分+贪心)

NOIP2012BLOCKADE贪心思想证明