CodeForces Round 552B. Make them Equal [Analysis]

2 minute read

The problem is to basically find the minimum non-negative integer D such that we can either add D to an element of the array, subtract D from an element of the array, or don’t modify the element at all and make all the elements of the array equal. It’s quite easy to see a brute force solution: we can try out all the possible values of D on the sorted (in ascending) array of inputs. If this is the case for some D all the elements in the array must equal to a[0] + D (i.e. the first element of the sorted array + D).

Because $1 <= a[i] <= 100$ and $1 <= n <= 100$ and the brute force algorithm has time complexity of $O(n^2)$ this code passes all the test cases within the time limit.

#include <iostream>
#include <cstdio>
#include <algorithm> 
using namespace std;
int a[111];
int main(int argc,char **argv){
  int n;
  scanf("%d",&n);
  for (int i = 0; i < n; i++){
    scanf("%d",&a[i]);
  }
  sort(a,a+n);
  for (int d = 0; d <= a[n-1]; d++){
    int target = a[0]+d;
    bool ans = true;
    for (int i = 0; i < n; i++){
      if (a[i] != target && abs(target-a[i]) != d){
        ans = false;
        break;
      }
    }
    if (ans){
      return !printf("%d\n",d);
    }
  }
  puts("-1");
  return 0;
}

However, this is not a very smart solution. What if $n > 10000$? In this case a quadratic solution will not work. We need to come up with something more clever. Suppose we sort the array a and get rid of all the duplicate elements of a (so the array a only contains unique elements). We can actually observe that if $n = 1$, then D = 0 because we don’t have to change anything. If $n = 2$, then we have two possible candidates for D: $(a[1]-a[0])/2$ if $a[1]-a[0]$ is even or $a[1]-a[0]$ if $a[1]-a[0]$ is odd. If $n = 3$ then we can only find a possible value for $D$ if and only if $a[1]-a[0] = a[2]-a[1]$. In this case we can increase a[0] by D and decrease a[2] by $a[1]-a[0]$ so that all the elements would be equal to a[1]. For $n >= 4$ we see that it is not possible to find a suitable D because even if the difference of consecutive elements are equal, there is no way to add some number to each elements of the array to make them all equal to a single value.
This solution has a performance of $O(1)$, which is much better than the above brute force solution.

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int MAXN = 111;
bool exist[MAXN];
int main(int argc,char **argv){
  int n,x;
  scanf("%d",&n);
  vector<int> a;
  for (int i = 0; i < n; i++){
    scanf("%d",&x);
    if (!exist[x]){
      exist[x] = true;
      a.push_back(x);
    }
  }
  sort(a.begin(),a.end()); // a only contains distinct values at this point
  if (a.size() >= 4){
    printf("-1\n");
  }else if (a.size() == 3){
    if (a[1]-a[0] == a[2]-a[1]){
      printf("%d\n",a[1]-a[0]);
    }else{
      puts("-1");
    }
  }else if (a.size() == 2){
    if ((a[1]-a[0])%2 == 0){
      printf("%d\n",(a[1]-a[0])/2);
    }else{
      printf("%d\n",a[1]-a[0]);
    }
  }else if (a.size() == 1){
    puts("0");
  }
  return 0;
}