从HashMap的一组值中找到模式,通过根本不指示任何模式来打破联系

时间:2019-02-25 02:31:46

标签: java algorithm data-structures

HashMap看起来像:

Keys: 1, 2, 4

Values: 1, 2, 1

此处的模式为2,因为它的值是该组值中的最高值。

但是,如果

Keys: 1, 2, 4

Values: 1, 2, 2

然后就没有模式了。对于较小的测试用例,我可以得到预期的输出,但是不确定在这里是否存在逻辑错误,不适用于较大的输出,如果数值很大并且不适合整数,则不会。

“计数”是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 :(得分:1)

您的代码不适用于此输入:

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

因为您要在发现重复项后立即设置mode = -1,而不是在结束时进行设置。

您可以尝试以下代码,该代码在EntrySet上进行2次传递。一次找到最大值,然后检索具有该最大值的条目。

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的值,可以使用LongBigInteger

答案 1 :(得分:0)

正如Kartik所说,您是正确的,您的代码中有错误。最后还有一个循环:找到对应于该值的键后,您需要立即中断该循环,否则mode可能会在以后的迭代中再次更改,从而导致错误的结果。例如

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

在这种情况下,您的代码将正确地确定最高计数为3。查找对应密钥的循环将首先将3更改为1,然后将下一次更改为1至2。因此结果为2,这是不正确的。基本问题是,出于两个目的,您正在使用相同的变量mode,首先是模式的计数,其次是模式的kay。不要那样做混乱的风险过高。

我想提出解决方案:

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