Найдя режим из набора значений из HashMap, разорвите связи, не указав режим вообще - PullRequest
0 голосов
/ 25 февраля 2019

HashMap будет выглядеть следующим образом:

Keys: 1, 2, 4

Values: 1, 2, 1

Режим здесь будет 2, поскольку его значение является наибольшим из набора значений.

Однако, если

Keys: 1, 2, 4

Values: 1, 2, 2

Тогда режима нет.Я получаю ожидаемый результат для меньших тестовых случаев, которые у меня есть, но не уверен, есть ли здесь логическая ошибка, которая не будет работать для больших выходов / если значения очень велики и не поместятся в целое число.

"count" - это HashMap.

Мой код:

            for (HashMap.Entry<Integer, Integer> entry : count.entrySet()) {
                int curr = entry.getValue();
                if (curr > mode) {
                    mode = curr;
                }
                else if (curr == mode) {
                    mode = -1;
                }
            }

            if (mode != -1) {
                for (HashMap.Entry<Integer, Integer> entry : count.entrySet()) {
                    if (entry.getValue() == mode) {
                        mode = entry.getKey();
                    }
                }
            }

Ответы [ 2 ]

0 голосов
/ 25 февраля 2019

Как уже сказал Kartik, вы правы, в вашем коде есть ошибки.В конце концов, в цикле есть еще один: вам нужно выйти из него, как только вы найдете ключ, соответствующий значению, или mode может быть снова изменен в более поздней итерации, что приведет к неверному результату.Например,

new HashMap<>(Map.of(1, 3, 2, 1))

В этом случае ваш код правильно определит, что наибольшее количество равно 3. Цикл для поиска соответствующего ключа сначала изменится с 3 на 1, а в следующий раз - с 1 на 2. Таким образом, результат2, что неверно.Основная проблема заключается в том, что вы используете одну и ту же переменную, mode, для двух целей: сначала счет режима, затем код режима.Не делай этого.Риск путаницы слишком велик.

Я хотел бы попытаться найти решение:

public static OptionalInt getModeIfUnique(Map<Integer, Integer> count) {
    Optional<Integer> maxCount = count.values().stream().max(Comparator.naturalOrder());
    OptionalInt modeKey = maxCount.flatMap(mc -> {
                        // Map containing only the entries having max count
                        Map<Integer, Integer> allModes = new HashMap<>(count);
                        allModes.values().removeIf(c -> c < mc);
                        if (allModes.size() == 1) {
                            return Optional.of(allModes.keySet().iterator().next());
                        } else {
                            return Optional.empty();
                        }
                    })
            .map(OptionalInt::of)
            .orElse(OptionalInt.empty());
    return modeKey;
}

Испытание:

    // Kartik’s example - should give no mode
    System.out.println(getModeIfUnique(Map.of(1, 2, 2, 2, 4, 1)));
    // My example - should give 1
    System.out.println(getModeIfUnique(Map.of(1, 3, 2, 1)));
    // Empty map - should give no mode
    System.out.println(getModeIfUnique(Map.of()));

Вывод:

OptionalInt.empty
OptionalInt[1]
OptionalInt.empty
0 голосов
/ 25 февраля 2019

Ваш код не будет работать для этого ввода:

HashMap<Integer, Integer> count = new HashMap<>();
count.put(1, 2);
count.put(2, 2);
count.put(4, 1);

, потому что вы устанавливаете mode = -1, как только вы найдете дубликат вместо того, чтобы делать это в конце.

Вы можете попробовать следующий код, который делает 2 прохода на EntrySet.Один раз, чтобы найти максимальное значение, а затем извлечь записи, имеющие это максимальное значение.

Integer max = count.values().stream()
        .max(Integer::compareTo)
        .orElse(-1);
List<Integer> maxEntries = count.entrySet().stream()
        .filter(e -> e.getValue().equals(max))
        .map(Map.Entry::getKey)
        .collect(Collectors.toList());
Integer mode = maxEntries.size() == 1 ? maxEntries.get(0) : -1; //if there is a tie, mode is -1
System.out.println(mode);

Чтобы иметь возможность хранить значения больше Integer, вы можете использовать Long и BigInteger.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...