0
votes

I got a question to answer with the best complexity we can think about.

We got one sorted array (int) and X value. All we need to do is to find how many places in the array equals the X value.

This is my solution to this situation, as i don't know much about complexity. All i know is that better methods are without for loops :X

class Question
{
    public static int mount (int [] a, int x)
    {
        int first=0, last=a.length-1, count=0, pointer=0;
        boolean found=false, finish=false;
        if (x < a[0] || x > a[a.length-1])
                return 0;
        while (! found) **//Searching any place in the array that equals to x value;**
        {
            if ( a[(first+last)/2] > x)
                last = (first+last)/2;
            else if ( a[(first+last)/2] < x)
                first = (first+last)/2;
            else
            {
                pointer = (first+last)/2;
                count = 1;
                found = true; break;
            }
            if (Math.abs(last-first) == 1)
            {
                if (a[first] == x)
                {
                    pointer = first;
                    count = 1;
                    found = true;
                }
                else if (a[last] == x)
                {
                    pointer = last;
                    count = 1;
                    found = true;
                }
                else
                    return 0;
            }
            if (first == last)
            {
                if (a[first] == x)
                {
                    pointer = first;
                    count = 1;
                    found = true; 
                }
                else
                    return 0;
            }
        }
        int backPointer=pointer, forwardPointer=pointer;
        boolean stop1=false, stop2= false;
        while (!finish) **//Counting the number of places the X value is near our pointer.**
        {
            if (backPointer-1 >= 0)
                if (a[backPointer-1] == x)
                {
                    count++;
                    backPointer--;
                }
                else
                    stop1 = true;
            if (forwardPointer+1 <= a.length-1)
                if (a[forwardPointer+1] == x)
                {
                    count++;
                    forwardPointer++;
                }
                else
                    stop2 = true;
            if (stop1 && stop2)
                finish=true;
        }
        return count;
    }
    public static void main (String [] args)
    {
        int [] a = {-25,0,5,11,11,99};
        System.out.println(mount(a, 11));
    }
}

The print command count it right and prints "2".

I just want to know if anyone can think about better complexity for this method.

Moreover, how can i know what is the time/space-complexity of the method?

All i know about time/space-complexity is that for loop is O(n). I don't know how to calculate my method complexity.

Thank a lot!

Editing: This is the second while loop after changing:

        while (!stop1 || !stop2) //Counting the number of places the X value is near our pointer.
    {
        if (!stop1)
        {
            if ( a[last] == x )
            {
                stop1 = true;
                count += (last-pointer);
            }
            else if ( a[(last+forwardPointer)/2] == x )
            {
                if (last-forwardPointer == 1)
                {
                    stop1 = true;
                    count += (forwardPointer-pointer);
                }
                else
                    forwardPointer = (last + forwardPointer) / 2;
            }
            else
                last = ((last + forwardPointer) / 2) - 1;
        }
        if (!stop2)
        {
            if (a[first] == x)
            {
                stop2 = true;
                count += (pointer - first);
            }
            else if ( a[(first+backPointer)/2] == x )
            {
                if (backPointer - first == 1)
                {
                    stop2 = true;
                    count += (pointer-backPointer);
                }
                else
                    backPointer = (first + backPointer) / 2;
            }
            else
                first = ((first + backPointer) / 2) + 1;
        }
    }

What do you think about the changing? I think it would change the time complexity to O(long(n)).

1

1 Answers

0
votes

First let's examine your code:

The code could be heavily refactored and cleaned (which would also result in more efficient implementation, yet without improving time or space complexity), but the algorithm itself is pretty good.

What it does is use standard binary search to find an item with the required value, then scans to the back and to the front to find all other occurrences of the value.

In terms of time complexity, the algorithm is O(N). The worst case is when the entire array is the same value and you end up iterating all of it in the 2nd phase (the binary search will only take 1 iteration). Space complexity is O(1). The memory usage (space) is unaffected by growth in input size.

You could improve the worst case time complexity if you keep using binary search on the 2 sub-arrays (back & front) and increase the "match range" logarithmically this way. The time complexity will become O(log(N)). Space complexity will remain O(1) for the same reason as before.

However, the average complexity for a real-world scenario (where the array contains various values) would be very close and might even lean towards your own version.