自学内容网 自学内容网

[M差分] lcxx. 访问消失节点的最少时间(差分+贪心+读题+思维)

1. 题目来源

链接:xx. 使差值相等的最少数组改动次数

2. 题目解析

挺有意思的一道差分题目,来自与 2024年07月20日,lc 第135双周三的 Q3。全场大约 500 人做出来。算是一个比较难的 Q3 了,看起来大家对差分数组的知识理解和应用,还有所不足啊哈哈。

思路:

  • 首先读题,题目有要求: nums[i] <= k,所以所有可能出现的 X 都是在 [0, k] 之间。

  • 看数据范围,1e5 的时间范围,动态规划肯定也不行了,枚举 i,枚举 X 都是没啥前途的了。

  • 那么思路就被限定在了:分类讨论、贪心。这类 O(n) 算法里面了。

  • 看下我们的操作,假定 a=nums[i], b = nums[n - i - 1], d = |a-b|,如果只修改一个数的话,可以获取到的最大取值范围即:m=max(a, k - a, b, k - b),也就是说:

  • 0<=X<d 时,只需要操作一次,即可让两数差值等于这个 X。

  • X=d 时,无需操作

  • d< x <= m 时,也只需要操作一次,即可让两数差值等于这个 X。

  • x > m 时,我们只能操作两次,才能让两数差值等于这个 X。

所以,可以遍历所有的数,求得 d,分别记录变成各个 X 的操作次数。

在上面的讨论,将 X 分段进行了讨论,我们需要将 [0, d) 这个区间段的所有 X 都需要 +1,因为都是等价的 X,所以比较自然的引入了 差分数组,给区间整体加上固定值。

最后,前缀和求和差分数组即可,每个下标都是 X 的需要的操作数。


挺不错的题目,需要一点分类讨论的思想,差分练习不错的题目。要时刻谨记:

  • 差分操作是可以给一段区间加上一个固定的数。

  • 时间复杂度 O ( n ) O(n) O(n)
  • 空间复杂度 O ( 1 ) O(1) O(1)

class Solution {
public:
    int minChanges(vector<int>& nums, int k) {
        int n = nums.size();
        int f[k + 2]; // 统计所有 X 的操作次数
        memset(f, 0, sizeof(f));

        // 枚举每个数对
        for (int i = 0; i < n / 2; i ++ ) {
            int a = nums[i], b = nums[n - i - 1];
            int d = abs(a - b);
            int m = max({a, k - a, b, k - b});  // 枚举数对最大的变化范围,在此一定有:m>=d

            // 差分数组记录 落在各个区间 X 的操作数
            // 0 <= X < d
            f[0] ++ , f[d] --;
            // d < X <= m
            f[d + 1] ++ ,f[m + 1] -- ;
            // x >= m
            f[m + 1] += 2 ;
        }

        int res = n;
        for (int i = 0, s = 0; i < k + 1; i ++ ) {  // 差分求和,统计 X=i 需要的操作总数
            s += f[i];
            res = min(res, s);
        }

        return res;
    }
};

原文地址:https://blog.csdn.net/yl_puyu/article/details/140580541

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!