2010-05-17 3 views
20

У меня есть переменное число ArrayList, которое мне нужно найти для пересечения. Реалистичный колпачок на количество наборов строк, вероятно, около 35, но может быть больше. Я не хочу никакого кода, просто идеи о том, что может быть эффективным. У меня есть реализация, которую я собираюсь начать кодировать, но хочу услышать некоторые другие идеи.Эффективное обнаружение пересечения переменного числа наборов строк

В настоящее время, просто думая о моем решении, похоже, что у меня должно быть асимптотическое время работы Θ (n).

Спасибо за помощь!

tshred

Edit: Для того, чтобы уточнить, я просто хочу знать, есть ли более быстрый способ сделать это. Быстрее, чем Θ (n).

+0

Спасибо за помощь всем! Строки фактически находятся внутри объектов в уже существующем списке массивов, поэтому я оставлял их в массивах. Мне никогда не приходилось использовать классы Java-классов, которые будут упомянуты, но определенно будут их использовать. Я ценю рекомендации. Проблема решена. – tshred

ответ

32

Set.retainAll() как вы находите пересечение двух наборов. Если вы используете HashSet, то преобразование ArrayList s в Set s и использование retainAll() в цикле над всеми из них на самом деле O (n).

+1

Убей меня :) –

+1

Вам нужно только обернуть один из списков в наборе. – Hans

+0

Ожидается, что он будет только в O (n). Это не худший случай! –

0

Сортируйте их (n lg n), а затем выполните двоичные поиски (lg n).

2

Лучшим вариантом было бы использование HashSet для хранения содержимого этих списков вместо ArrayList. Если вы можете это сделать, вы можете создать временный набор HashSet, к которому вы добавляете элементы, которые нужно пересечь (используйте метод putAll (..)). В tempSet.retainAll (storedSet) и tempSet будет находиться пересечение.

4

Еще одна идея - если ваши массивы/наборы имеют разные размеры, имеет смысл начать с самого маленького.

1

Вы можете использовать одиночный HashSet. Метод add() возвращает false, когда объект является alredy в наборе. добавление объектов из списков и отметка количества ложных значений возврата даст вам объединение в наборе + данных для гистограммы (а объекты с числом + 1, равным количеству списков, являются вашим перекрестком). Если вы перечислите счет в TreeSet, вы можете обнаружить пустое пересечение раньше.

7

Принятый ответ в порядке; как обновление: поскольку Java 8 имеет несколько более эффективный способ найти пересечение двух Set s.

Set<String> intersection = set1.stream() 
    .filter(set2::contains) 
    .collect(Collectors.toSet()); 

Причина это немного более эффективным потому, что оригинальный подход должен был добавить элементы set1 тогда снова пришлось удалить, если они не были в set2. Этот подход только добавляет к набору результатов то, что должно быть там.

Строго говоря, вы могли бы сделать это и до Java 8, но без Stream s код был бы немного более трудоемким.

Если оба набора отличаются значительным размером, вы предпочтете перетекать через меньший.

+0

Хорошее примечание: нет потоковой передачи по более мелкому. Это связано с тем, что потоковое одно итерация, в то время как выполняется поиск другого (большего) набора (хешем для «HashSet», который является [O (1)] (https://stackoverflow.com/questions/6574916/hashset- просмотровый-сложность)). –

Смежные вопросы