-2

Greetings to all programmers!

I would like to present my method to search an unsorted array(of Integers/Strings) with less time complexity. Linear search method is commonly used for unsorted arrays that has a worst case time complexity of O(n).

I have modified the linear search conditions to also check the last element of array, thus reducing iterations. Please check out this code and provide your valuable feedback. Here the worst case time complexity for searching through the loop in O(n/2). [EDIT - Through answers, came to know that it is still O(n)]

for(int i=0, len=arr.length; i<len; i++){
        if(arr[i].equals(somethingToFind) || arr[--len].equals(somethingToFind)){
            System.out.println("Found");
            break;
        }
    }

Also, we can modify the if statement to include more conditions like checking arr[i+1] along with arr[len-1] and increment i by 2 to reduce iterations. Just for example!

I would like to know if the above code has any performance improvement when compared to linear search. What's your thoughts? Thanks for your responses!

EDIT - Thank you so much for that brilliant responses! Yes, I thought that extra conditions would cost performance, but just wanted to clarify on it. Great responses given on the BigONotation and Time Complexity. Thank you! :-)

tk1
  • 25
  • 2
  • 5
  • 4
    No, it's still O(n). You can't search an unsorted array in less than O(n). – Kayaman Aug 01 '17 at 16:51
  • @Kayaman not true, with Quantum computation, you can – developer_hatch Aug 01 '17 at 16:53
  • 1
    @DamianLattenero Yea, but that's not available until Java 13. – Kayaman Aug 01 '17 at 16:54
  • 1
    Think about it like this -- how could you *guarantee* that the element exists in an unsorted array, without looking at every element in the array? And looking at every element in the array is O(n), regardless of how you traverse it. – Andrew Sun Aug 01 '17 at 16:55
  • Even if one were to accept the accounting trick of comparing two elements at a time, it's still a constant times n, so O(n). – phatfingers Aug 01 '17 at 16:56
  • @Kayaman be careful! Can I took your word? If it's not ready for Java 13 your complete reputation as programmer will be crashed :P ahhaha ;). Perhaps sooner as you think – developer_hatch Aug 01 '17 at 16:57
  • 2
    @Thuvi, another way to look at it. Given your solution, if the set grew by 10 times the size, it would still take 10 times as long to process. Linear growth. – phatfingers Aug 01 '17 at 17:01
  • O(n/2) = O(n), but it's not even halving the running time - you're essentially just moving your comparisons and in/decrements around - you still have `n` `equals` calls and `n` in/decrements (it's true that you're halving the `i – Bernhard Barker Aug 01 '17 at 17:52

5 Answers5

4

When searching in complete unknown structures, we can not do better than a linear search does. The bottom line is: We need to take a look at each element in order to find a specific element (yields O(n)).

It does not matter if we search from left to right or from right to left or from both sides or even from random positions. If we have no knowledge over the structure than it simply does not matter.


However if we know something, for example that the structures are sorted or any other kind of special distribution, then we can exploit that and take advantage of it.

This are the only cases where we can develop techniques that yield better complexities, for example binary search for sorted structures.


It holds that, as long as you do not restrict the structure of the input (so allow every arbitrary input structure) then you can always find a special kind of inputs that yield n-lookups, for every algorithm.

If I got you right then your special algorithm processes the list from both sides, so one linear search starting from left and one from right and in the end they meet in the middle.

For this special algorithm you can generate inputs where the desired element is exactly placed in the middle, then you have again n-lookups.


At this point I think it could be possible that you got confused by the characteristics of Big-O-Notation.

If you, in one iteration, make two comparisons or even 100, then you will not reduce the time complexity. While it is correct that your algorithm in the end will only have n/2 iterations (because it makes 2 lookups in one iteration) it will again yield n-lookups.

And also note that even if your algorithm really would just take a look at n/2 elements then it would also be in the set of O(n) again, by definition (you can forget about all constant factors like 1/2 in the O-notation).

Just as a rough overview: In the set O(g(x)) are all functions f(x) for which f(x) <= C * g(x) where C is an arbitrary constant. It is okay if it does not hold for all x values but it most exist a bound x' from where it is true, so for all x > x'.

These functions are, for example, all in O(n):

  • 100 * n
  • 1/200 * n
  • 5 + 6n
  • n - 10000000
Zabuzard
  • 25,064
  • 8
  • 58
  • 82
1

As @Kayaman commented, searching a unsorted array is always O(n)

There is a prove in the answer of this question: Array search NP complete

Suppose with your algoritmn, you double the size of the array. How much more time will you algoritmn require? Double the amount of time. That is what O(n) means.

Stijn Haezebrouck
  • 387
  • 1
  • 2
  • 14
  • for clarity, the referred question states: Array search NP complete. A linear complexity O(n) is not in fact NP complete. That is also explained in that questions' answer – Stijn Haezebrouck Aug 01 '17 at 18:41
0

Assume you write

if(arr[0].equals(somethingToFind) || arr[1].equals(somethingToFind) || arr[2].equals(somethingToFind) || arr[3].equals(somethingToFind) || arr[4].equals(somethingToFind)){
            System.out.println("Found");
            break;
       }

in worst case, your target is in last index. Therefore it will be O(n).

yılmaz
  • 1,818
  • 13
  • 15
  • This is not what OP wrote though, nor is it in the same order as the order in which OP's code will do the checks. – Bernhard Barker Aug 01 '17 at 17:53
  • as OP gave an example of arr[i].equals(somethingToFind) || arr[--len].equals(somethingToFind), i turned it into more concrete style to show that, whatever you do, you will end up with O(n) in this kind of search. – yılmaz Aug 02 '17 at 04:48
0

Even if you put 2 conditions in a single IF, you're accessing the array 2 times per iteration. Also in the asymptotic notation O(n/2) is still equals to O(n). So you can't get a better result than O(n) for searching an element in an unsorted array.

Gio G.
  • 21
  • 3
0

What you are doing (unknowingly) is called loop unrolling, i.e. replicating the instructions inside the loop body to lessen the number of iterations and the loop overhead.

In this case what you did is perfectly counterproductive, for two reasons:

  • you trade a loop exit test for a shortcut-or, probably a little harder to branch-predict.

  • you scan memory at two places instead of one, and one in reverse. This is cache-unfriendly.

As others said, it is impossible to perform this lookup in less than N comparisons at worst. (The worst case occurs when the searched element is not in the list.)