0

Consider array of INT of positive numbers:

    {1,3,6,4,7,6,9,2,6,6,6,6,8}

Given: only one number is repeated, return number and positions with efficient algorithm.

Any ideas for efficient algorithms?

5
  • Algorithm efficiency is often relative not only to the algorithm used but the size of the input as well. Commented Feb 8, 2011 at 21:57
  • it is not a homework. This is interview question at microsoft Commented Feb 8, 2011 at 21:57
  • Ok, not homework, but still; what have you tried? Commented Feb 8, 2011 at 22:16
  • @T.E.D.: one of many possible duplicates: stackoverflow.com/questions/4895079/… Commented Feb 8, 2011 at 22:28
  • @Paul That questions duplicates the number once only. This asks for the number of repetitions. Commented Feb 9, 2011 at 22:47

7 Answers 7

4

One possible solution is to maintain an external hash map. Iterate the array, and place the indices of values found into the hash map. When done, you now know which number was duplicated and the indices of the locations it was found at.

Sign up to request clarification or add additional context in comments.

3 Comments

So note that we are told there is a single repeated entry. So the hash map only needs to store a single index. So define its target as a single integer; initially set these to zero. As soon as we go to store a new index and find there is already a non-zero entry, we're done. The hash approach not only gives O(n), but may not even require iterating the whole array. OK, slightly simplistic in assuming unique hashes, which will depend on the max value. A more complex hash target will not change the order of the performance.
@Keith: Not so - the algorithm needs to return the indices of the duplicated values. If we back out before iterating the entire array, we never found them all.
Stand corrected. +1. Misread thinking only a single repetition. But thinking again, we can still be able to use the fact that only a single number is repeated to simplify the hash, and keep a separate list for the repeats, rather that a list for every hash.
1

In an interview situation, I guess its your chance to ask around the question, for example, how many numbers? what range of numbers? you could state that an optimum algorithm could change depending.

That gives you a chance to show how you solve problems.

If the range of ints in the array is small enough then you could create another array to keep count of the number of times each integer is found then go linearly through the array accumulating occurrence counts, stopping when you get to an occurance count of two.

Comments

0

Hash will do just fine in here. Add numbers to it one by one, each time checking if number's already in there.

5 Comments

Won't sorting lose the original indices, which we need to return?
@James You're right, I've removed that after rereading my post. And sorting is slower anyway.
we need to return repeated number and position of that repeated number in the array. In this case(repeated number: 6, position 2,5,8,9,10,11)
@James: There is no mention of sorting in the answer here... nevermind. Looks like that was removed.
@chota If you know the number, how to find all its positions in the array?
0

Well, there probably is some trick (usually is). But just off the cuff, you should be able to sort the list (O(nlogn)). Then its just a matter of finding a number that is the same as the next one (linear search - O(n)). You'd have to sort it as tuples of values and original indices of course, so you could return that index you are looking for. But the point is that the upper bound on an algorithim that will do the job should be O(nlogn).

If you just go through the list linerally, you could take each index, then search through the rest of the list after it for a matching index. I think that's roughly equivalent to the work done in a bubble sort, so it would probably be O(n^2), but a simple one.

I really hate trick questions as interview questions. They are kind of like optical illusions: Either you see it or you don't, but it doesn't really say anything bad about you if you don't see the trick.

1 Comment

@Carra - ...only if you have things arranged so there's no hash collisions. As n approaches infinity, hashing's time-behavior devolves to whatever the time-behvior of its collision strategy is.
0

I'd try this:

  1. all elms of list have to be looked at (=> loop over the list)
  2. before the repeated elm is known, store elm => location/index in a hash/dictionary
  3. as soon as the second occurence of the repeated element is found, store its first postion (from the hash) and the current position in the result array
  4. compare further elms of list against the repeated elm, append found locations to the result array

in code:

Function locRep( aSrc )
  ' to find repeated elm quickly
  Dim dicElms : Set dicElms = CreateObject( "Scripting.Dictionary" )
  ' to store the locations
  Dim aLocs   : aLocs       = Array()
  ' once found, simple comparison is enough
  Dim vRepElm : vRepElm     = Empty
  Dim nIdx
  For nIdx = 0 To UBound( aSrc )
      If vRepElm = aSrc( nIdx ) Then ' repeated elm known, just store location
         ReDim Preserve aLocs( UBound( aLocs ) + 1 )
         aLocs( UBound( aLocs ) ) = nIdx
      Else ' repeated elm not known
         If dicElms.Exists( aSrc( nIdx ) ) Then ' found it
            vRepElm = aSrc( nIdx )
            ReDim aLocs( UBound( aLocs ) + 2 )
            ' location of first occurrence
            aLocs( UBound( aLocs ) - 1 ) = dicElms( aSrc( nIdx ) )
            ' location of this occurrence
            aLocs( UBound( aLocs )     ) = nIdx
         Else
            ' location of first occurrence
            dicElms( aSrc( nIdx ) ) = nIdx
         End If
      End If
  Next
  locRep = aLocs
End Function

Test run:

-------------------------------------------------
     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
Src: 1 3 6 4 7 6 9 2 6 6 6 6 8
Res: 2 5 8 9 10 11
ok

Src:
Res:
ok

Src: 1 2 3
Res:
ok

Src: 1 1 2 3 4 5 6
Res: 0 1
ok

Src: 1 2 3 4 5 6 6
Res: 5 6
ok

=================================================

Comments

0
using namespace std;
list<int> find_duplicate_idx(const vector<int>& A)
{
hash_map<int, int> X;
list<int> idx;
for ( int i = 0; i < A.size(); ++ i ) {
  hash_map<int, int>::iterator it = X.find(A[i]);
  if ( it != X.end() ) {
    idx.push_back(it->second);
    idx.push_back(i);
    for ( int j = i + 1; j < A.size(); ++j )
      if ( A[j] == A[i] )
        idx.push_back(j);  
    return idx;
  }
  X[A[i]] = i;
}
return idx;
}

This is a solution my friend provided. Thank you SETI from mitbbs.com

Comments

0

Use the hash-map to solve it :

private int getRepeatedElementIndex(int[] arr) {

    Map<Integer, Integer> map = new HashMap();
    // find the duplicate element in an array
    for (int i = 0; i < arr.length; i++) {
        if(map.containsKey(arr[i])) {
            return i;
        } else {
            map.put(arr[i], i);
        }
    }
    throw new RuntimeException("No repeated element found");
}

Time complexity : O(n)

Space complexity : O(n)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.