Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding an element in partially sorted array

I had a following interview question.

There is an array of nxn elements. The array is partially sorted i.e the biggest element in row i is smaller than the smallest element in row i+1. How can you find a given element with complexity O(n)

Here is my take on this:

You should go to the row n/2.And start compare for example you search for 100 and the first number you see is 110 so you know it's either in this row or in rows above now you go n/4 and so on.

From the comments

Isn't it O(n * log n) in total? He has to parse through every row that he reaches per binary search, therefore the number of linear searches is multiplied with the number of rows he will have to scan in average. – Martin Matysiak 5 mins ago.

I am not sure that is a right solution. Does anyone have something better

like image 965
Yakov Avatar asked Jun 04 '11 09:06

Yakov


People also ask

What is partially sorted array?

In computer science, partial sorting is a relaxed variant of the sorting problem. Total sorting is the problem of returning a list of items such that its elements all appear in order, while partial sorting is returning a list of the k smallest (or k largest) elements in order.

Which algorithm is best for partially sorted array?

​Many sorting algorithms are available, but the one which is best suited for the almost sorted array is the insertion sort.

How do you find the pivot element of an array?

Algorithm to find pivot element of a rotated array. Find the middle index as (leftIndex + rightIndex)/2. Let middle index be mid. Check if inputArray[mid] is a pivot element. If (inputArray[mid-1] > inputArray[mid] < inputArray[mid+1]) is true then inputArray[mid] is pivot element.


2 Answers

Your solution indeed takes O(n log n) assuming you're searching each row you parse. If you don't search each row, then you can't accurately perform the binary step.

O(n) solution:

Pick the n/2 row, instead of searching the entire row, we simply take the first element of the previous row, and the first element of the next row. O(1).
We know that all elements of the n/2 row must be between these selected values (this is the key observation). If our target value lies in the interval, then search all three rows (3*O(n) = O(n)).

If our value is outside this range, then continue in the binary search manner by selecting n/4 if our value was less than the range, and 3n/4 row if the value was greater, and again comparing against one element of adjacent rows.

Finding the right block of 3 rows will cost O(1) * O(log n), and finding the element will cost O(n).

In total O(log n) + O(n) = O(n).

like image 173
davin Avatar answered Sep 27 '22 22:09

davin


Here is a simple implementation - since we need O(n) for finding an element within a row anyhow, I left out the bin-search...

void search(int n[][], int el) {
    int minrow = 0, maxrow;
    while (minrow < n.length && el >= n[minrow][0])
        ++minrow;
    minrow = Math.max(0, minrow - 1);
    maxrow = Math.min(n.length - 1, minrow + 1);
    for (int row = minrow; row <= maxrow; ++row) {
        for (int col = 0; col < n[row].length; ++col) {
            if (n[row][col] == el) {
                System.out.printf("found at %d,%d\n", row, col);
            }
        }
    }
}
like image 25
dcn Avatar answered Sep 27 '22 23:09

dcn