2

I am solving a problem where I have been given an array A of length N and an integer 0<K<N. We need to make sum of all subarrays(including circular) of length K equal in min operations. In one operation, we can either increment or decrement an element of array by 1.

I am unable to think of an algorithm to do this. For K=1, I can calculate the mean and then calculate the sum of absolute difference between mean and the array elements. But for larger K, can anybody give me a hint?

Ashish
  • 33
  • 3
  • For K=1, I think you want the **median** instead of the **mean**. – user3386109 Apr 10 '22 at 07:44
  • For K=2, if `N` is odd, then you need to make all of the elements equal. But if `N` is even, you can alternate between two values. For example `[5, 2, 5, 2]` works because the sum of each subarray is 7, but `[5, 2, 5, 2, 5]` doesn't work because the wrap-around sum is 10. So in the latter case, the final array would have to be `[5, 5, 5, 5, 5]`. – user3386109 Apr 10 '22 at 07:57
  • Did you solve it ? – ng.newbie Apr 10 '22 at 17:36

2 Answers2

3

Hint: the final array should be whole repetitions of the first K elements, like [1,2,3,1,2,3,1,2,3] due to the circular constraint. Hence if N is not divisible by K, then all elements should be equal, and they should all be changed to the median of the array. If N is even, taking the N/2 or N/2+1 smallest element is the same. Otherwise, you need to make a[0], a[K], ... equal, a[1], a[K+1], ... equal and so on. Solve them independently by changing each to the corresponding median.

PunnyBunny
  • 185
  • 1
  • 10
  • 1
    If N is relatively prime to K, then all elements must be equal. The size of the repeating group is GCD(N,K) – Matt Timmermans Apr 10 '22 at 15:04
  • @FunnyBunny Could tell me how you deduced that `the final array should be whole repetitions of the first K elements, like [1,2,3,1,2,3,1,2,3] due to the circular constraint.` ? – ng.newbie Apr 10 '22 at 17:48
  • @FunnyBunny What if the circular constraint was not there ? – ng.newbie Apr 10 '22 at 18:08
  • @ng.newbie To be clear, it's not a repetition of the **original** first K elements of the array. If the input array is `[a,b,c,d,e,f,g,h,i]`, then the output array is `[x,y,z,x,y,z,x,y,z]` where `x=median(a,d,g)`, `y=median(b,e,h)`, and `z=median(c,f,i)`. – user3386109 Apr 10 '22 at 18:32
  • 1
    @ng.newbie Let the first `K` elements sum to `S`, then the sum of next `K` elements, i.e. `a[1]+a[2]+...+a[K]` also needs to be `S`, but we fixed `a[1], a[2], ..., a[K-1]`, so `a[K]` is `S-a[1]-a[2]-...-a[K-1]` which is `a[0]`. By a similar argument, `a[K+1]=a[1]` and so on. For the circular constraint, you can think of duplicating the array at the back, i.e. `a[1], a[2], ..., a[N-1], a[0], a[1], ...`, then similarly, `a[N-1]=a[K-1]`, `a[N-2]=a[K-2]` and so on. – PunnyBunny Apr 11 '22 at 04:20
  • @FunnyBunnyleaksmemory I think the circular constraint adds nothing extra to the problem. Am I correct ? – ng.newbie Apr 11 '22 at 09:02
0

I hope the following code answers your problem:

class Solution {
public:
    long long int calc(vector<int>& nums) {
        long long int n = nums.size();
        sort(nums.begin(), nums.end());
        if (n % 2 == 0) {
            long long int num1 = nums[n / 2];
            long long int num2 = nums[(n / 2) - 1];
            long long int cnt1 = 0, cnt2 = 0;
            for (auto num : nums) {
                cnt1 += abs(num - num1);
                cnt2 += abs(num - num2);
            }
            return min(cnt1, cnt2);
        } else {
            long long int num = nums[n / 2];
            long long int cnt = 0;
            for (auto num : nums) {
                cnt += abs(num - num);
            }
            return cnt;
        }
        return 0;
    }

    long long int makeSubKSumEqual(vector<int>& nums, int k) {
        long long int n = nums.size();
        if (__gcd(n, (long long)k) != 1) {
            long long int ans = 0;
            for (int i = 0; i < __gcd(n, (long long)k); i++) {
                int j = i;
                vector<int> v;
                while (j < n) {
                    v.push_back(nums[j]);
                    j += __gcd(n, (long long)k);
                }
                ans += calc(v);
            }
            return ans;
        } else {
            return calc(nums);
        }
    }
};