2

Problem: Find the non duplicate items from two given array (not the sorted array). If array one is {1, 2, 3} and second array is having {2, 3, 4} then result should be {1,4}.

What i did: I achieved it through using Set. But it seems O(n2).

What i need: Is there any other algorithm which can be written in much optimized for?

My code:

package src;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.TreeSet;

public class GetNonDuplicate {

    public static void main(String[] args) {

        Integer[] arrayOne = {1, 2, 3};
        Integer[] arrayTwo = {2, 3, 4};
        List<Integer> resultList = new ArrayList<Integer>();

        List<Integer> listOfArrayOne =  new ArrayList<Integer>(Arrays.asList(arrayOne));
        TreeSet<Integer> setOne = new TreeSet<Integer>(listOfArrayOne);
        System.out.println("SetOne is : " + setOne);

        for (Integer elem2 : arrayTwo) {

            boolean exists = setOne.add(elem2);
            System.out.println("For elem2 [" + elem2 + "], exists [" + exists + "]." );
            if (exists) {
                resultList.add(elem2);
            }
        }

        System.out.println(resultList);

        List<Integer> listOfArrayTwo =  new ArrayList<Integer>(Arrays.asList(arrayTwo));
        TreeSet<Integer> setTwo = new TreeSet<Integer>(listOfArrayTwo);
        System.out.println("setTwo is : " + setTwo);

        for (Integer elem1 : arrayOne) {

            boolean exists = setTwo.add(elem1);
            System.out.println("For elem2 [" + elem1 + "], exists [" + exists + "]." );
            if (exists) {
                resultList.add(elem1);
            }
        }

        System.out.println(resultList);

    }

}
Sam
  • 859
  • 3
  • 12
  • 23
  • Are the arrays ordered at the start, as in your example? – hatchet - done with SOverflow Jan 26 '15 at 04:58
  • Looks like you want the symmetric difference of the elements of the two arrays. If that's the problem, check here: http://stackoverflow.com/q/8064570/1065197 – Luiggi Mendoza Jan 26 '15 at 05:00
  • 2
    sort both arrays and iterate them using 2 pointers (one for each array) would be one way to do it in O(nlogn) time and O(1) space. With O(n) space and O(n) time you could just make a `Map` that would count all the occurrences of each number and then just print the number which have count 1. – Mateusz Dymczyk Jan 26 '15 at 05:00
  • Thank you Mateusz Dymczyk for the great idea :) – Sam Jan 26 '15 at 05:25
  • Hi hatchet, Though my example looks sorted but as per problem statement should un-sorted. That's why i thought of using TreSet rather HashSet. – Sam Jan 26 '15 at 05:26

2 Answers2

0

A solution that basically uses only Collections API (i.e. no explicit iteration) is

    Integer[] arrayOne = {1, 2, 3};
    Integer[] arrayTwo = {2, 3, 4};
    Set<Integer> set1 = new HashSet<>(Arrays.asList(arrayOne));
    Set<Integer> set2 = new HashSet<>(Arrays.asList(arrayTwo));
    Set<Integer> uniqueTo1 = new HashSet<>(set1);
    uniqueTo1.removeAll(set2);
    Set<Integer> uniqueTo2 = new HashSet<>(set2);
    uniqueTo2.removeAll(set1);
    Set<Integer> result = new HashSet<>(uniqueTo1);
    result.addAll(uniqueTo2);

    System.out.println(result);

This should run in O(n) time, unless I am missing something: conversion of the arrays to lists is O(n), as is the creation of the Sets, remove is constant time on a HashSet, so removeAll(...) is O(n).

James_D
  • 201,275
  • 16
  • 291
  • 322
  • 1
    Sadly it doesn't add the unique elements from `arrayTwo` so it doesn't get "4". – Elliott Frisch Jan 26 '15 at 05:27
  • Thank you James for this idea. But still looking if it can more optimized. – Sam Jan 26 '15 at 05:27
  • Yeah, too late to be doing this, but I fixed it, and I think it still runs in `O(n)`. – James_D Jan 26 '15 at 05:29
  • James, can't we go for TreeSet rather HashSet? – Sam Jan 26 '15 at 05:31
  • `remove` operations on a `TreeSet` are `O(log(n))`, so `removeAll` is `O(n log(n))` and it would be slower in general. – James_D Jan 26 '15 at 05:31
  • Thank you James for sharing the nice observation. – Sam Jan 26 '15 at 05:38
  • @Sam if you want O(n) time then you also need O(n) space, if you want O(1) space then you need O(nlogn) time unless the initial array is sorted. O(n) time and O(1) space isn't feasible, neither is anything below O(n) time as you need to check each element at least once. – Mateusz Dymczyk Jan 26 '15 at 07:47
0

make collections of each types of items in the array. and then collect those array variables which have only one item, hence, unique items

Arpan Adhikari
  • 127
  • 1
  • 9
  • Arpan, can u please elaborate a little? – Sam Jan 26 '15 at 18:09
  • find a way to group the items by their similarity ( or the behaviors that make them equal ) and store them in two dimensional array. Now, check the resulting two dimensional array to see if any block has only one item.If it has only one item then it means that the item in the block is unique. – Arpan Adhikari Jan 26 '15 at 23:23