Skip to content

3224. Minimum Array Changes to Make Differences Equal 👍

  • Time: $O(n)$
  • Space: $O(n)$
 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
class Solution {
 public:
  int minChanges(vector<int>& nums, int k) {
    const int n = nums.size();
    const int pairSize = n / 2;
    int ans = n;
    unordered_map<int, int> diffCount;  // {abs(nums[-i - 1] - nums[i]): freq}
    // oneChangeCount[i] := the number of pairs that need only one change to to
    // achieve a difference of `i`
    vector<int> oneChangeCount(k + 1);

    for (int i = 0; i < pairSize; ++i) {
      const int a = nums[i];
      const int b = nums[n - i - 1];
      ++diffCount[abs(a - b)];
      ++oneChangeCount[max({a, b, k - a, k - b})];
    }

    // prefixOneChangeCount[i] := the number of pairs that need only one change
    // to achieve a difference >= `i`
    // prefixOneChangeCount[i] = sum(oneChangeCount[i..k])
    vector<int> prefixOneChangeCount{oneChangeCount};

    for (int i = k - 1; i >= 0; --i)
      prefixOneChangeCount[i] += prefixOneChangeCount[i + 1];

    for (const auto& [diff, freq] : diffCount) {
      const int oneChange = prefixOneChangeCount[diff] - freq;
      const int twoChanges = (pairSize - prefixOneChangeCount[diff]) * 2;
      ans = min(ans, oneChange + twoChanges);
    }

    return ans;
  }
};
 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
class Solution {
  public int minChanges(int[] nums, int k) {
    final int n = nums.length;
    final int pairSize = n / 2;
    int ans = n;
    Map<Integer, Integer> diffCount = new HashMap<>(); // {abs(nums[-i - 1] - nums[i]): freq}
    // oneChangeCount[i] := the number of pairs that need only one change to
    // achieve a difference of `i`
    int[] oneChangeCount = new int[k + 1];

    for (int i = 0; i < pairSize; ++i) {
      final int a = nums[i];
      final int b = nums[n - i - 1];
      diffCount.merge(Math.abs(a - b), 1, Integer::sum);
      ++oneChangeCount[Math.max(Math.max(a, b), Math.max(k - a, k - b))];
    }

    // prefixOneChangeCount[i] := the number of pairs that need only one change
    // to achieve a difference >= `i`
    // prefixOneChangeCount[i] = sum(oneChangeCount[i..k])
    int[] prefixOneChangeCount = oneChangeCount.clone();

    for (int i = k - 1; i >= 0; --i)
      prefixOneChangeCount[i] += prefixOneChangeCount[i + 1];

    for (Map.Entry<Integer, Integer> entry : diffCount.entrySet()) {
      final int diff = entry.getKey();
      final int freq = entry.getValue();
      final int oneChange = prefixOneChangeCount[diff] - freq;
      final int twoChanges = (pairSize - prefixOneChangeCount[diff]) * 2;
      ans = Math.min(ans, oneChange + twoChanges);
    }

    return ans;
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution:
  def minChanges(self, nums: list[int], k: int) -> int:
    pairSize = len(nums) // 2
    diffCount = collections.Counter()  # {nums[-i - 1] - nums[i]: freq}
    # oneChangeCount[i] := the number of pairs that need only one change to
    # to achieve a difference of `i`
    oneChangeCount = [0] * (k + 1)

    for i in range(pairSize):
      a = nums[i]
      b = nums[-i - 1]
      diffCount[abs(a - b)] += 1
      oneChangeCount[max(a, b, k - a, k - b)] += 1

    # prefixOneChangeCount[i] := the number of pairs that need only one change
    # to achieve a difference >= `i`
    # prefixOneChangeCount[i] = sum(oneChangeCount[i..k])
    prefixOneChangeCount = list(
        itertools.accumulate(reversed(oneChangeCount)))[::-1]

    return min(prefixOneChangeCount[diff] - freq +  # one change
               (pairSize - prefixOneChangeCount[diff]) * 2  # two changes
               for diff, freq in diffCount.items())