1

There is one question which is bugging me, and somehow, I cannot figure out what to do with it. Suppose an array {9,1,2,4,1,2,2} is given. The unique elements in the array are 9 and 4. The output array should be {1,2,1,2,2} . My idea to preserve the order and find duplicates is to use a LinkedHashMap which will have the entries and the count of occurrence of the entries.

The problem is maintaining the order of the elements. Once I put the entries in the hashMap, the order will vanish.

Salvador Dali
  • 214,103
  • 147
  • 703
  • 753
CyprUS
  • 4,159
  • 9
  • 48
  • 93

6 Answers6

1

There's nothing making the array vanish. Just iterate over the array, checking whether the value in the map is greater than one.

Pete Kirkham
  • 48,893
  • 5
  • 92
  • 171
1

So an easy way to do this is to first count the number of each element (can be done in O(n)), iterate over the counter and put all elements with count = 1 in a set (also in O(n)).

Now run through the original list and print all elements that are not in your set (also O(n)). So the solution will run in O(n) time and space.

And here is 2 line solution in python:

from collections import Counter
arr = [9,1,2,4,1,2,2]

unique = {k for k, v in Counter(arr).iteritems() if v == 1}
print [i for i in arr if i not in unique]
Salvador Dali
  • 214,103
  • 147
  • 703
  • 753
1

Just count elements and check if the total count of current element is greater than one.

Code example (C++11):

#include <iostream>
#include <unordered_map>
#include <vector>

int main() {
  std::vector<int> to_split = {9, 1, 2, 4, 1, 2, 2};

  std::vector<int> unique, not_unique;
  std::unordered_map<int, int> counter;
  for (int elem : to_split) {
    ++counter[elem];
  }
  for (int elem : to_split) {
    if (counter[elem] > 1) {
      not_unique.push_back(elem);
    } else {
      unique.push_back(elem);
    }
  }

  std::cout << "Unique: " << std::endl;
  for (int elem : unique) {
    std::cout << elem << " ";
  }
  std::cout << std::endl;
  std::cout << "Not unique:" << std::endl;
  for (int elem : not_unique) {
    std::cout << elem << " ";
  }
  std::cout << std::endl;
  return 0;
}

Output:

Unique:
9 4 
Not unique:
1 2 1 2 2 
SashaMN
  • 708
  • 5
  • 16
0

Just brainstorming a bit, but I somehow have to think about how an unstable sorting algorithm can be made stable: decorate, sort, undecorate.

Given your input list, you iterate over it, adding the position of the item to a list in a map.

for (i = 0; i < length; i++) {
    value = list[i]
    map[value].append(i)
}

Then, remove all items with count 1, and reconstruct the list (which you can do, because you have the indices in the map).

Thinking about it further: why not just do 1 loop counting, and then another loop to construct the filtered list? Probably even has better performance, I think O(n). (1 iteration to do the counts, 1 iteration to re-construct the new list)

0

I would do it like this:

  1. create a

    HashMap count =new HashMap();

  2. iterate your array store the array-value as key and the count of the value as value in the hashmap

  3. iterate the array a second time and remove value from the array if count to the key is one.

osanger
  • 2,276
  • 3
  • 28
  • 35
0

Similar to fedekau's approach, but not counting:

int[]numbers = {9,1,2,4,1,2,2};
int guessedDistinct = (int)(2 * Math.sqrt(numbers.length));
final Map<Number, Boolean>
    seenBefore = new HashMap<>(guessedDistinct);
for (int i : numbers)
    seenBefore.put(i, seenBefore.containsKey(i));
int[] out = Arrays.stream(numbers)
    .filter(i -> seenBefore.getOrDefault(i, false))
    .toArray();
System.out.println(Arrays.toString(out));

(or try to avoid "finding i twice" in filling seenBefore:

for (int i : numbers)
    seenBefore.compute(i, (k, seen) -> null != seen);
Community
  • 1
  • 1
greybeard
  • 2,249
  • 8
  • 30
  • 66