tags:

views:

476

answers:

10

I was asked this question in an interview. Although the interview was for dot net position, he asked me this question in context to java, because I had mentioned java also in my resume.

How to find the index of an element having value X in an array ?

I said iterating from the first element till last and checking whether the value is X would give the result. He asked about a method involving less number of iterations, I said using binary search but that is only possible for sorted array. I tried saying using IndexOf function in the Array class. But nothing from my side answered that question.

Is there any fast way of getting the index of an element having value X in an array ?

+14  A: 

As long as there is no knowledge about the array (is it sorted? ascending or descending? etc etc), there is no way of finding an element without inspecting each one.

Also, that is exactly what indexOf does (when using lists).

f1sh
"... without inspecting each one until you find it.", actually. If your element is the first one, you don't need to inspect every element n the array/list.
Joachim Sauer
Sorry, i thought that was obvious! Anyone who doesn't mind that in his implementation doesn't deserve to run it...
f1sh
But that doesn't mean that it couldn't be done faster i.e. by parallelization.
Peladao
+1  A: 

Puneet - in .net its:

string[] testArray = {"fred", "bill"};
var indexOffset = Array.IndexOf(testArray, "fred");

[edit] - having read the question properly now, :) an alternative in linq would be:

string[] testArray = { "cat", "dog", "banana", "orange" };
int firstItem = testArray.Select((item, index) => new
{
    ItemName = item,
    Position = index

}).Where(i => i.ItemName == "banana")
  .First()
  .Position;

this of course would find the FIRST occurence of the string. subsequent duplicates would require additional logic. but then so would a looped approach.

jim

jim
That method does not exist in Java... a) What Array class are you using? b) method names don't start with uppercase letters in java
f1sh
It seems you havn't read the entire question, I asked them for using the IndexOf function but they were asking me to write logic myself. They were saying that the simple loop you have written is correct but this can be improved and made in less number of iterations. Just think about it!!!
Puneet Dudeja
f1sh - oops, correct and corrected... puneet - yes, can see that now. kinda rushed it a bit!!
jim
@Puneet Dudeja well, since it's not possible to do this in less number of iterations, they wanted you to say so and explain why. Either that or they're just plain wrong.
Samuel_xL
@jim: This is basically the *opposite* of what the OP wants (!); you are simply adding *more* overhead (the construction of many new objects of anonymous type) to what is effectively still the determination of an item's index by enumeration (using `Where`/`First`).
Dan Tao
+3  A: 

If a binary search isn't possible (beacuse the array isn't sorted) and you don't have some kind of advanced search index, the only way I could think of that isn't O(n) is if the item's position in the array is a function of the item itself (like, if the array is [10, 20, 30, 40], the position of an element n is (n / 10) - 1).

gustafc
Having the value of an array depend on it's index is some kind of sorting - at least is gives you a pretty good hint of how the elements are arranged.
f1sh
This is basically how hash tables work.
Michael Borgwardt
+1  A: 

It's a question about data structures and algorithms (altough a very simple data structure). It goes beyond the language you are using.

If the array is ordered you can get O(log n) using binary search and a modified version of it for border cases (not using always (a+b)/2 as the pivot point, but it's a pretty sophisticated quirk).

If the array is not ordered then... good luck.

He can be asking you about what methods you have in order to find an item in Java. But anyway they're not faster. They can be olny simpler to use (than a for-each - compare - return).

There's another solution that's creating an auxiliary structure to do a faster search (like a hashmap) but, OF COURSE, it's more expensive to create it and use it once than to do a simple linear search.

helios
I think you meant O(log n) for an ordered array.
Phil
@Phil: Corrected. Thank you very much.
helios
A: 

Take a perfectly unsorted array, just a list of numbers in memory. All the machine can do is look at individual numbers in memory, and check if they are the right number. This is the "password cracker problem". There is no faster way than to search from the beginning until the correct value is hit.

Kevin Kostlan
A: 

Are you sure about the question? I have got a questions somewhat similar to your question.

Given a sorted array, there is one element "x" whose value is same as its index find the index of that element.

For example: //0,1,2,3,4,5,6,7,8,9,10
int a[10]={1,3,5,5,6,6,6,8,9,10,11};

at index 6 that value and index are same.

for this array a, answer should be 6.

This is not an answer, in case there was something missed in the original question this would clarify that.

Mani
what would be a correct answer to your question ? Is there a way to do this < O(n) ?
Samuel_xL
As far as I remember, the question was what I have asked here, because I confirmed it 2-3 times before replying.
Puneet Dudeja
+5  A: 

A practical way of finding it faster is by parallel processing.

Just divide the array in N parts and assign every part to a thread that iterates through the elements of its part until value is found. N should preferably be the processor's number of cores.

Peladao
Nice idea. But is it really useful to scale it using the processor's core count? The VM doesn't divide the thread equally amongst all cores, or does it?
f1sh
java has the ParallelArray (generic) and ParallelLongArray (primitive) for this. http://gee.cs.oswego.edu/dl/jsr166/dist/extra166ydocs/extra166y/ParallelLongArray.html. The `indexOf` operation is implemented using the N partitions scheme.
mdma
@f1sh - in practice (on Windows, where most of my experience lies) you find cpu usage can approach 100% for all cores when using a ForkJoinPool sized to the number of available cores. And this also gives you the benefit of using more L1 cache than with the single-threaded case, which since L1 is usually dedicated to each core/pair of cores.
mdma
That is the responsibility of the VM. In general, using multiple threads on a multi-core CPU should always be faster than just one thread. (This is disregarding the overhead of dividing the array and starting threads. The array should of course be sufficiently large to justify parallelization).
Peladao
For greater parallelism you could always assign the work to a GPU or two: http://www.jcuda.de/
DrDipshit
+9  A: 

How to find the index of an element having value X in an array ?

This would be fast:

int getXIndex(int x){
    myArray[0] = x;
    return 0;
}
DrDipshit
your function should receive the array as a parameter. Other than that, excellent answer (which also illustrates one danger of TDD):)
Mikeage
I must start writing my code like this - it saves so much time.
mdma
+1 very funny! :-D
fortran
+1  A: 

Maybe he wants to test your knowledge about Java.

There is Utility Class called Arrays, this class contains various methods for manipulating arrays (such as sorting and searching)

http://download.oracle.com/javase/6/docs/api/java/util/Arrays.html

In 2 lines you can have a O(n * log n) result:

    Arrays.sort(list); //O(n * log n)
    Arrays.binarySearch(list, 88)); //O(log n)
Torres
Sorting is already `O(n*log(n))` in the best case for mergesort (that is the algorithm implemented in Java utils if I remember well), so your solution is worse than linear (`O(n*log(n)^2)` indeed).
fortran
should be O(n*log n)as the sorting (assuming comparison model) takes O(n*log n)and the binary search is O(log n)so the total is O(logn + nlogn) = O(nlogn)
Ahmed Kotb
@Ahmed you're quite right! I'd update my comment but the edition time has expired :-s
fortran
You´re right Ahmed, I was only thinking in the search problem. I´ve fixed it, thank you.
Torres
Extract for the documentation: _Sorts the specified array of bytes into ascending numerical order. The sorting algorithm is a tuned **quicksort**, adapted from Jon L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November 1993). This algorithm offers n*log(n) performance on many data sets that cause other quicksorts to degrade to quadratic performance._
Torres
+1  A: 

Use a quantum computer:

http://en.wikipedia.org/wiki/Grover%27s_algorithm

fortran