Для простого, но, возможно, не очень эффективного алгоритма я бы сделал это так:
1.разверните карту до списка.
практически произнесено: переберите карту и добавьте ключ 'value-times' в новый список.Наконец, сортируйте список.
//...
List<Integer> field = new ArrayList<Integer>();
for (Integer key:map) {
for (int i = 0; i < map.get(key); i++) {
field.add(key);
}
}
Collections.sort(field);
2.вычислите медиану
Теперь вам нужно реализовать метод int calculateMedian(List<Integer> sorted)
.Это зависит от того, какая медиана вам нужна.Если это просто пример медианы, то результатом является либо самое среднее значение (для списков с нечетным числом элементов), либо среднее значение двух средних значений (для списков с четной длиной).Обратите внимание, что список должен быть отсортирован!
(Ссылка: Пример Медиана / Википедия )
ОК, ОК, хотя Крис не упомянулэффективность, вот идея, как рассчитать медиану образца (!) без расширения карты ...
Set<Integer> sortedKeys = new TreeSet<Integer>(map.keySet()); // just to be sure ;)
Integer median = null; // Using Integer to have a 'invalid/not found/etc' state
int total = 0;
for (Integer key:sortedKeys) {
total += map.get(key);
}
if (isOddNumber(total)) { // I don't have to implement everything, do I?
int counter = total / 2; // index starting with 0
for (Integer key:sortedKeys) {
middleMost -= map.get(key);
if (counter < 0) {
// the sample median was in the previous bin
break;
}
median = key;
}
} else {
int lower = total/2;
int upper = lower + 1;
for (Integer key:sortedKeys) {
lower -= map.get(key);
upper -= map.get(key);
if (lower < 0 && upper < 0) {
// both middlemost values are in the same bin
break;
} else (lower < 0 || upper < 0) {
// lower is in the previous, upper in the actual bin
median = (median + key) / 2; // now we need the average
break;
}
median = key;
}
}
(у меня нет компилятора под рукой - если он имеет много синтаксических ошибок, трактуйте его как псевдокод, пожалуйста;))