Search code examples
objective-casymptotic-complexity

How can I make the performance O(N) instead of O(N^2)?


I'm trying to understand how to make the time complexity better for this problem:

A non-empty zero-indexed array A consisting of N integers is given. The consecutive elements of array A represent consecutive cars on a road.

Array A contains only 0s and/or 1s: 0 represents a car traveling east, 1 represents a car traveling west.

The goal is to count passing cars. We say that a pair of cars (P, Q), where 0 ≤ P < Q < N, is passing when P is traveling to the east and Q is traveling to the west.

For example, consider array A such that:

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

We have five pairs of passing cars: (0, 1), (0, 3), (0, 4), (2, 3), (2, 4).

Write a function:

int solution(NSMutableArray *A);

that, given a non-empty zero-indexed array A of N integers, returns the number of pairs of passing cars.

The function should return −1 if the number of pairs of passing cars exceeds 1,000,000,000.

Assume that:

N is an integer within the range [1..100,000]; each element of array A is an integer that can have one of the following values: 0, 1.

Complexity:

expected worst-case time complexity is O(N); expected worst-case space complexity is O(1), beyond input storage (not counting the storage required for input arguments). Elements of input arrays can be modified.

Solution:

   int solution(NSMutableArray *A) {
// write your code in Objective-C 2.0

int counter = 0;

for (int i = 0; i < A.count; i++) {
    if ([A[i] intValue] == 0) {
        for (int j = i; j < A.count; j++) {
            if ([A[j] intValue] == 1) {
                counter++;
            }
        }
    }
}


return counter;
}

Right now the solution is running at O(N^2) due to the nested for loops. I cant seem to wrap my head around how to solve it in O(N) time. This isn't homework; I'm just refreshing algorithms for interviews.


Solution

  • Something like that?

    NSInteger solutionCountingDifferentDirections(NSMutableArray *A) {
        NSInteger multiplier = 1;
        NSInteger counter = 0;
        NSInteger firstCarDirection = A[0];
        for (NSInteger idx = 1; idx < A.count; idx++) {
            if (firstCarDirection == A[idx]) {
                multiplier++;
            }
            else {
                counter += multiplier;
            }
        }
    
        return counter;
    }
    

    EDIT: @RNar suggested that we don't count first cars with west direction so here's solution for that case:

    NSInteger solutionCountingFromFirstEastDirection(NSMutableArray *A) {
        NSInteger multiplier = 0;
        NSInteger counter = 0;
        for (NSInteger idx = 0; idx < A.count; idx++) {
            if (A[idx] == 0) {
                multiplier++;
            }
            else {
                counter += multiplier;
            }
        }
    
        return counter;
    }