【Leetcode】1775. Equal Sum Arrays With Minimum Number of Operations

题目地址:

https://leetcode.com/problems/equal-sum-arrays-with-minimum-number-of-operations/

给定两个只含 1 ∼ 6 1\sim 6 16的数组 A 1 A_1 A1 A 2 A_2 A2,允许将任一数组的任一数改为另一个值,改成的值必须也是 1 ∼ 6 1\sim 6 16。问最少改动多少个数就能让两个数组的总和相等。

A 1 A_1 A1长度为 l 1 l_1 l1 A 2 A_2 A2长度为 l 2 l_2 l2,不妨设 l 1 ≤ l 2 l_1\le l_2 l1l2,那么 A 1 A_1 A1可以变成的总和的范围是 [ l 1 , 6 l 1 ] [l_1,6l_1] [l1,6l1],同理 A 2 A_2 A2可以变成的总和范围是 [ l 2 , 6 l 2 ] [l_2,6l_2] [l2,6l2]。要使得两个总和相等,必须有 6 l 1 ≥ l 2 6l_1\ge l_2 6l1l2,否则就无解。接着暴力枚举 [ 6 l 1 , l 2 ] [6l_1,l_2] [6l1,l2]的所有数就可以了。对于某个和 x x x,我们看原来的和 s s s x x x之间的关系。如果 s > x s>x s>x,那么我们要将数组中的一部分数变小,由于我们希望改动的数字尽可能小,显然我们要从 6 6 6开始枚举, 6 6 6变成 1 1 1可以”消耗掉“ 5 5 5的差值,并且我们需要 ⌈ s − x 5 ⌉ \lceil\frac{s-x}{5}\rceil 5sx 6 6 6去做这样的改动,以此类推。如果 s < x s<x s<x同理。如果 s = x s=x s=x那就不用改了。代码如下:

class Solution {
 public:
  int minOperations(vector<int>& a1, vector<int>& a2) {
    int n = a1.size(), m = a2.size();
    if (n > m) return minOperations(a2, a1);

    if (m > 6 * n) return -1;
    vector<int> c1(7), c2(7);
    int s1 = 0, s2 = 0;
    for (int x : a1) c1[x]++, s1 += x;
    for (int x : a2) c2[x]++, s2 += x;

    int res = INT_MAX;
    for (int k = m; k <= 6 * n; k++)
      res = min(res, calc(s1, c1, k) + calc(s2, c2, k));
    return res;
  }

  int calc(int s, vector<int>& c, int t) {
    if (s == t) return 0;
    int res = 0;
    if (s >= t) {
      int d = s - t;
      for (int k = 6; k > 1; k--) {
        int kk = k - 1;
        if (c[k] * kk >= d)
          // 注意上取整的写法
          return res + (d + kk - 1) / kk;
        else
          res += c[k], d -= c[k] * kk;
      }
    } else {
      int d = t - s;
      for (int k = 1; k < 6; k++) {
        int kk = 6 - k;
        if (c[k] * kk >= d)
          return res += (d + kk - 1) / kk;
        else
          res += c[k], d -= c[k] * kk;
      }
    }
    return res;
  }
};

时间复杂度 O ( 6 max ⁡ { l A 1 , l A 2 } − min ⁡ { l A 1 , l A 2 } ) O(6\max\{l_{A_1},l_{A_2}\}-\min\{l_{A_1},l_{A_2}\}) O(6max{lA1,lA2}min{lA1,lA2}),空间 O ( 1 ) O(1) O(1)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值