4

I came across following problem:

'Find all the elements in an array which occur odd number of times'.

My thoughts about this are:

  1. Use HashMap: Add values in the array as keys in the HashMap. The value corresponding to each key will be number of times that key is encountered.

  2. Sort the array using Quick sort in O(N log N) and then traverse through the array to check which elements occur odd number of times.

What do you think, is there any other approach to this? If no, then which of these 2 approaches is better?

Thanks in advance!

Vikram
  • 3,996
  • 8
  • 37
  • 58

4 Answers4

15

You can modify your first approach to use a hash set instead of a hash map.

Create an initially empty hash set. Go through the elements of your array. For each element, check the hash set: if the current array element is not in the set, add it; otherwise, remove it.

When you reach the end of the array, your hash set will contain every object that occurs in your array an odd number of times.

Since accessing elements in a hash set is O(1), this algorithm has O(N) time complexity.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thanks for the answer. But, why `HashSet` and not `HashMap`? The advantage that `HashSet` avoids duplicate elements will not be of much help to us as we are anyway going to search for that element, if we find that then we are going to remove, else add. – Vikram Nov 05 '13 at 18:05
  • 1
    @Vikram With `HashMap` you are storing the explicit count. In Java that means storing a wrapped integer from which you need only its last bit (the one determining if it's even or odd) and that you are going to discard anyway. In other languages you would still be storing a full integer, which is wasteful when all you need is a single bit. – Sergey Kalinichenko Nov 05 '13 at 18:08
  • this answer shows why this person has 200k points...nice work – Tom Swifty Nov 05 '13 at 19:07
  • What if there are collisions, wouldn't hash set not have O(1) access then? – committedandroider Feb 23 '15 at 01:40
  • @committedandroider Assuming a good quality hash function, hast table is *amortized* O(1). An individual operation may take longer or shorter, but each operation is constant time on average over the course of N operations. – Sergey Kalinichenko Feb 23 '15 at 02:18
  • Can you elaborate on that? What would cause all the operations to average out? – committedandroider Feb 23 '15 at 04:40
  • @committedandroider Please look up [amortized analysis](http://stackoverflow.com/q/11102585/335858). – Sergey Kalinichenko Feb 23 '15 at 04:59
  • this is a nice solution.. but I have a doubt.. so, this case aren't we using up extra memory to store the results? is it considered to be using space or just simply returning the output? coz in the worst case where every element is present only once, we are simply copying the array to a HashSet – Sai Manoj Oct 14 '16 at 16:43
  • @SaiManoj Yes, this algorithm has O(n) space complexity - basically, you pay with more memory for better asymptotic complexity. – Sergey Kalinichenko Oct 14 '16 at 17:03
  • how will you handle even number. As per above, if number present than discard. How will handle in case of even occurrence, – user765443 Feb 06 '17 at 04:38
  • @user765443 Finding numbers with even counts is a different problem, so it has a different solution. – Sergey Kalinichenko Feb 06 '17 at 09:42
5

"Better" depends on context. Using the hash map or hash set will be faster and has the advantage of not modifying the original array, but it requires O(N) extra memory. Sorting and counting takes longer and modifies the array, but requires no extra memory.

Which solution you choose depends on whether you can afford the extra memory.

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
0

Basically this can be done as an exercise in rebalancing efficiency: you go through your list of numbers, and for each number you already have in your set, you delete it again. That way your comparison set is about half the size of the possible max. Of course, that does not change O(n lg n), and you get an allocation/deallocation on each step which is likely quite more expensive.

So it might be interesting to use a mixed strategy: quicksort is pretty fast, but you basically want to coalesce two entries whenever they are equal, and at least (n-1)/2 entries are equal. Quicksort does not really accommodate the removal of elements while sorting.

So with an array-based approach (to cut down on allocation costs), I'd rather use some heap-based approach. Whenever you chance upon equal elements, you remove one. Heap sort is pretty competitive with quicksort, and being able to prune the tree in advance is going to turn out helpful.

0

Find the number occurring odd number of times in an array in Java

package yourPackageNameGoesHere;

import java.util.*;

public class FindTheNumberOccurringOddNumberOfTimesInArray {
public static void main(String[] args) {
    int array [] = {20, 40, 50, 50, 20, 30, 30, 50, 20,20};
    findTheNumberOccurringOddNumberOfTimesInArray(array);
}

public static void findTheNumberOccurringOddNumberOfTimesInArray(int arr[]) {
    Map<Integer, Integer> map = new HashMap<>();

    for (int num : arr) {
        if (map.containsKey(num)) {
            map.put(num, map.get(num) + 1);
        } else {
            map.put(num, 1);
        }
    }
    for (int n : map.keySet()) {
        if (map.get(n) % 2 == 1) {
            System.out.println(n + " is occurring " + map.get(n) + " time(s).");
        }
    }
}

}

Bayram Binbir
  • 1,531
  • 11
  • 11