0

How do I get the element that appears once in a double array? Below is what I have tried, and the execution time is unacceptable. This will be ran against very huge arrays. There can only be one unique element.

public static double getUnique(double arr[]) {
    double res = 0.0;
    for (int i = 0; i < arr.length; i++){
        res = arr[i];
        int count = 0;
        for (int j = 0; j < arr.length; j++){
            if (res == arr[j]){
                count ++;
            }
            if(j == arr.length - 1){
                if(count == 1){
                    return res;
                }
            }
        }

    }
    return res;
}
  • Use a HashMap to count the occurrences. – Henry Nov 26 '18 at 12:32
  • Or sort the array and find the element which have distinct neighbors. It's O(n log(n)) and not O(n), but it requires no boxing, no entry allocations, and uses less memory, so maybe it's faster. You'd have to measure. – JB Nizet Nov 26 '18 at 12:38

2 Answers2

0

You can do something like this, this will count all doubles in a HashMap and return the first double of which the occurance is 1:

public static double getUniqueMine(double arr[]) {
    // Keep track of the occurances of doubles
    HashMap<Double, Integer> doubleOccurances = new HashMap<>();

    // Loop through all doubles
    for(double d : arr) {
        // Increment double count
        doubleOccurances.merge(d, 1, Integer::sum);
    }

    // Return the first item where the count is 1
    for(Entry<Double, Integer> values : doubleOccurances.entrySet()) {
        if(values.getValue() == 1) {
            return values.getKey();
        }
    }

    return 0.0;
}
Mark
  • 5,089
  • 2
  • 20
  • 31
  • It should really throw an exception, or return an OptionalDouble, rather than returning a valid, but incorrect value 0.0. Also, the for loop body can be replaced by `doubleOccurances.merge(d, 1, Integer::sum);` (which is shorter and more efficient) – JB Nizet Nov 26 '18 at 12:58
  • @JBNizet Agreed but the original question also returned `0.0` when there's no value found, so I stuck to that. – Mark Nov 26 '18 at 13:12
  • 1
    True that. I'll leave this comment there for the OP then. – JB Nizet Nov 26 '18 at 13:14
  • You are right. It should throw an exception or return an OptionalDouble. I appreciate your quick response. – marttronix Nov 26 '18 at 13:30
0

Using streams:

If you are sure that there is always one unique element:

public static double getUnique(double arr[]) {
    return  Arrays.stream(arr).boxed()
            .collect(Collectors.groupingBy(Function.identity(),Collectors.counting()))
            .entrySet().stream().filter(e->e.getValue() == 1).findFirst().get().getKey();
}

Else return a default value using:

public static double getUnique2(double arr[]) {
    return  Arrays.stream(arr).boxed()
            .collect(Collectors.groupingBy(Function.identity(),Collectors.counting()))
            .entrySet().stream().filter(e->e.getValue() == 1)
            .map(Map.Entry::getKey).findFirst().orElse(-1.);
}
Eritrean
  • 15,851
  • 3
  • 22
  • 28