Самый эффективный способ найти уникальные записи в большом наборе данных

1

Прежде всего, я даю понять, что это задание, и я не ожидаю полных закодированных ответов. Все, что я ищу, это советы и, возможно, фрагменты кода, которые мне помогают.

Итак, я читаю около 900 000 слов, которые хранятся в массиве. Мне нужно подсчитывать уникальные слова, используя отсортированный массив (или arraylist) в java.

До сих пор я просто перебираю данный массив и использую

Collections.sort(words); 

и Collections.binarySearch(words, wordToLook); для достижения его следующего:

OrderedSet set = new OrderedSet();
    for(String a : words){
        if(!set.contains(a)){
            set.add(a);
        }
    }

а также

public boolean contains(String word) {
    Collections.sort(uniqueWords);
    int result = Collections.binarySearch(uniqueWords, word);

    if(result<0){
        return false;
    }else{
        return true;
    }
}

Этот код имеет время работы около 60 секунд, но мне было интересно, есть ли какой-нибудь лучший способ сделать это, потому что запуск сортировки каждый раз, когда добавляется элемент, кажется очень неэффективным (но couse необходим, если я должен использовать бинарный поиск).

Будем очень благодарны за любую обратную связь. Благодарю.

  • 1
    Вы никогда не должны запускать сортировку каждый раз, когда добавляется элемент.
  • 0
    Да, но какой будет альтернатива?
Показать ещё 2 комментария
Теги:
arrays
arraylist
sorting
search

4 ответа

0
Лучший ответ

Таким образом, вы должны использовать отсортированный массив. Это нормально, поскольку вы (еще не) программируете в реальном мире.

Я предлагаю две альтернативы:

Первый использует двоичный поиск (который вы используете в своем текущем коде).

Я бы создал класс, который содержит два поля: слово (строка) и счетчик для этого слова (int). Вы построите отсортированный массив этих классов.

Начните с пустого массива и добавьте его, когда будете читать каждое слово. Для каждого слова выполните двоичный поиск слова в массиве, который вы строите. Поиск будет либо найти запись, содержащую слово (и вы увеличите счетчик), либо вы определите, что слово еще не находится в массиве.

Когда ваш двоичный поиск заканчивается, не найдя слово, вы создадите новый объект для хранения слова + count и добавьте его в массив в том месте, где закончился ваш поиск (будьте осторожны, чтобы убедиться, что ваша логика действительно делает это правильно чтобы сохранить сортировку списка). Конечно, для ваших слов установлено значение 1.

Другая альтернатива:

Прочитайте все свои слова в списке и отсортируйте его. После сортировки все дубликаты будут рядом друг с другом в списке.

Вы пройдете по этому отсортированному списку один раз и создадите список слов + count, когда идете. Если следующее слово, которое вы видите, совпадает с последним словом + count, увеличивайте счет. Если это новое слово, добавьте новое слово + счет в список результатов с count = 1.

0

Вы всегда можете использовать компаратор для получения уникальных значений.

  List newList = new ArrayList(new Comparator() {
        @Override
        public int compare(words o1, words o2) {
            if(o1.equalsIgnoreCase(o2)){
                return 0;
            }
            return 1;
        }
    });

Теперь посчитайте:

words - newList = no. повторяющихся значений.

Надеюсь это поможет!!!!

0

Я бы не использовал отсортированный массив. Я бы создал Map<String, Integer> где ключ является вашим словом, а значение - числом числа вхождений слова. Когда вы читаете каждое слово, сделайте что-то вроде этого:

Integer count = map.get(word);
if (count == null) {
    count = 0;
}
map.put(word, count + 1);

Затем просто перейдите по набору записей карты и сделайте все, что вам нужно для подсчета.

Если вы знаете или можете оценить количество уникальных слов, вы должны использовать этот номер в конструкторе HashMap (так что вы не разрастаете карту много раз).

Если вы используете отсортированный массив, время выполнения не может быть больше, чем пропорционально NlogN (где N - количество слов в вашем списке). Если вы используете HashMap, вы можете достичь времени выполнения, которое линейно растет с помощью N (вы сохраняете коэффициент logN).

Еще одно преимущество использования карты - используемая память пропорциональна количеству уникальных слов, а не полному количеству слов (при условии, что вы строите карту при чтении слов, вместо того, чтобы читать все слова в коллекции, а затем добавлять их к карте).

  • 0
    Дело в том, что мне бы очень хотелось использовать карту, я вынужден использовать отсортированный массив, потому что это требование ..
0
public static int countUnique(array) {
    if(array.length == 0) return 0;
    int count = 1;
    for i from 1 to array.length - 1 {
        if(!array[i].equals(array[i - 1])) count++;
    }
    return count;
}

Это алгоритм O(N) в псевдокоде для подсчета количества уникальных записей в отсортированном массиве. Идея заключается в том, что мы подсчитываем количество переходов между группами равных элементов. Тогда число уникальных записей - это число переходов плюс один (для первой записи).

Надеемся, вы увидите, как применить этот алгоритм к вашему массиву после сортировки элементов.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню