• 【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 ss<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;
      }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    时间复杂度 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)

  • 相关阅读:
    Java中的命名规则
    安兰德写作竞赛可以获得多少奖金?
    代码随想录算法训练营第四十九天| 139.单词拆分
    Spring Security学习(一)——快速开始
    【毕业设计】 基于Django的会议室预定系统
    SpringBoot/Spring扩展点系列之初始化和销毁的3种办法 - 第438篇
    公开课:1小时攻破云原生面试难点-孟凡杰
    【QT ScrollArea】手势滑动ScrollArea窗口实现
    12:面试题:react,vue中的key有什么作用?(key的内部原理)
    【Leetcode】146.LRU缓存
  • 原文地址:https://blog.csdn.net/qq_46105170/article/details/127712995