Просто poll()
очередь, если ее наименьший элемент меньше (в вашем случае имеет худший рейтинг) текущего элемента.
static <V extends Comparable<? super V>>
PriorityQueue<V> nbest(int n, Iterable<V> valueGenerator) {
PriorityQueue<V> values = new PriorityQueue<V>();
for (V value : valueGenerator) {
if (values.size() == n && value.compareTo(values.peek()) > 0)
values.poll(); // remove least element, current is better
if (values.size() < n) // we removed one or haven't filled up, so add
values.add(value);
}
return values;
}
Предполагается, что у вас есть некоторый класс комбинаций, который реализует Comparable
, который сравнивает комбинации по их рейтингу.
Редактировать: Просто чтобы уточнить, Iterable
в моем примере не нужно предварительно заполнять. Например, вот Iterable<Integer>
, который даст вам все натуральные числа, которые int
может представлять:
Iterable<Integer> naturals = new Iterable<Integer>() {
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
int current = 0;
@Override
public boolean hasNext() {
return current >= 0;
}
@Override
public Integer next() {
return current++;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
};
Как видите, потребление памяти очень скромное - для более чем 2 миллиардов значений вам нужно два объекта (Iterable
и Iterator
) плюс один int
.
Конечно, вы можете довольно легко адаптировать мой код, чтобы он не использовал Iterable
- я просто использовал его, потому что это элегантный способ представления последовательности (также я слишком много делал на Python и C # ☺ ).