Перетяжка, Дом карьеры
Перетяжка, Дом карьеры
Перетяжка, Дом карьеры

Сгенерированные случайным образом числа передаются методу. Напишите программу расчета медианы, динамически отслеживающую новые поступающие значения

Аватар Типичный программист
Отредактировано

4К открытий4К показов

Одно из возможных решений — использовать две кучи разных приоритетов: максимальная куча (maxHeap) для значений выше среднего и минимальная куча (minHeap) для значений ниже среднего. Это позволит разделить элементы примерно поровну с двумя значениями — вершинами куч. Теперь найти среднее значение очень просто.

Что означает «примерно поровну»? «Примерно» означает, что при нечетном количестве чисел в одной из куч окажется лишнее число. Можно сформулировать:

			если maxHeap.size() > min.Heap.size(), то heap1.top() будет средним значением;
если maxHeap.size() == minHeap.size(), то средним значением будет среднее значений maxHeap.top() и min.Heap.top().
		

В алгоритме с балансировкой мы гарантируем, что maxHeap будет всегда содержать дополнительный элемент.

Алгоритм работает следующим образом. Если новое значение меньше или равно среднему, оно помещается в maxHeap, в противном случае оно попадает в minHeap. Размеры куч могут совпадать или в maxHeap может быть один дополнительный элемент. Это требование легко выполнить, сдвигая элемент из одной кучи в другую. Среднее значение находится в вершине. Обновления занимают O(log(n)) времени.

			private Comparator<Integer> maxHeapComparator;
private Comparator<Integer> minHeapComparator;
private PriorityQueue<Integer> maxHeap, minHeap;

public void addNewNumber(int randomNumber) {
	/*Заметьте: addNewNumber поддерживает условие, что
	*maxHeap.size() >= minHeap.size() */
	if (maxHeap.size() >= minHeap.size()) {
		if ((minHeap.peek() != null) &&
		randomNumber > minHeap.peek()) {
			maxHeap.offer(minHeap.poll());
			minHeap.offer(randomNumber);
		} else {
			maxHeap.offer(randomNumber);
		}
	} else {
		if(randomNumber < maxHeap.peek()) {
			minHeap.offer(maxHeap.poll());
			maxHeap.offer(randomNumber)
		}
		else {
		minHeap.offer(randomNumber);
		}
	}
}

public static double getMedian() {
	/*maxHeap является всегда по крайней мере столь же большой,
	*как minHeap. Если maxHeap пуста, то minHeap тоже пуста. */
	if (maxHeap.isEmpty()) {
		return 0;
	}
	if(maxHeap.size() == minHeap.size()) {
		return ((double)minHeap.peek()+(double)maxHeap.peek()) / 2;
	} else {
		/* Если maxHeap и minHeap разных размеров, то 
		* в maxHeap есть один дополнительный элемент.
		* Возвращаем вергину кучи maxHeap */
		return maxHeap.peek();
	}
}
		

Разбор задачи по книге «Карьера программиста. Как устроиться на работу в Google, Microsoft или другую ведущую IT-компанию»

Следите за новыми постами
Следите за новыми постами по любимым темам
4К открытий4К показов