Search code examples
c#algorithmpuzzle

Algorithm: Max Counters


I have the following problem:

You are given N counters, initially set to 0, and you have two possible operations on them:

  • increase(X) − counter X is increased by 1,
  • max_counter − all counters are set to the maximum value of any counter.

A non-empty zero-indexed array A of M integers is given. This array represents consecutive operations:

  • if A[K] = X, such that 1 ≤ X ≤ N, then operation K is increase(X),
  • if A[K] = N + 1 then operation K is max_counter.

For example, given integer N = 5 and array A such that:

A[0] = 3
A[1] = 4
A[2] = 4
A[3] = 6
A[4] = 1
A[5] = 4
A[6] = 4

the values of the counters after each consecutive operation will be:

(0, 0, 1, 0, 0)
(0, 0, 1, 1, 0)
(0, 0, 1, 2, 0)
(2, 2, 2, 2, 2)
(3, 2, 2, 2, 2)
(3, 2, 2, 3, 2)
(3, 2, 2, 4, 2)

The goal is to calculate the value of every counter after all operations.

I did the following solution but it runs at O(NK) where K = length of array A.

public int[] solution(int N, int[] A) {
    int[] result = new int[N];
    int maximum = 0;

    for (int K = 0; K < A.Length; K++)
    {
        if (A[K] < 1 || A[K] > N + 1)
            throw new InvalidOperationException();

        if (A[K] >= 1 && A[K] <= N)
        {
            result[A[K] - 1]++;

            if (result[A[K] - 1] > maximum)
            {
                maximum = result[A[K] - 1];
            }
        }
        else
        {
            // inefficiency here
            for (int i = 0; i < result.Length; i++)
                result[i] = maximum;
        }
    }

    return result;
}

Could anyone show me how this can be better done with O(N + K) where K is the length of array A? Sorry for may terrible coding, I am doing these exercises to improve my programming. Thanks!


Solution

  • This is what I came up with, but I am not sure if it works 100%:

    public int[] solution(int N, int[] A) {
        int[] result = new int[N];
        int maximum = 0;
        int resetLimit = 0;
    
        for (int K = 0; K < A.Length; K++)
        {
            if (A[K] < 1 || A[K] > N + 1)
                throw new InvalidOperationException();
    
            if (A[K] >= 1 && A[K] <= N)
            {
                if (result[A[K] - 1] < resetLimit) {
                    result[A[K] - 1] = resetLimit + 1;
                } else {
                    result[A[K] - 1]++;
                }
    
                if (result[A[K] - 1] > maximum)
                {
                    maximum = result[A[K] - 1];
                }
            }
            else
            {
                // inefficiency here
                //for (int i = 0; i < result.Length; i++)
                //    result[i] = maximum;
                resetLimit = maximum;
            }
        }
    
        for (int i = 0; i < result.Length; i++)
            result[i] = Math.Max(resetLimit, result[i]);
    
        return result;
    }