【问题标题】:Java HashSet (Long vs Integer)Java HashSet(长与整数)
【发布时间】:2017-06-04 04:33:29
【问题描述】:

我正在解决这个问题,(来自 Project Euler 的 41),我注意到 HashSet 的 contains 方法对于 Long 与 Integer 的工作方式不同(我可能在这里错了,如果我错了,请纠正我)。

问题是——

我们可以说一个 n 位数字是泛数字的,如果它使用 所有数字 1 到 n 恰好一次。例如,2143 是 4 位数字 pandigital,也是素数。

存在的最大 n 位泛数素数是多少?

我检查号码是否为 Pandigital 的代码是 -

private static boolean isPan(Long n) {
        HashSet<Long> list = new HashSet<Long>();
        int count = 0;
        while(n != 0){
            list.add(n%10);
            count++;
            n /= 10;
        }
        for(int i = 9; i>count; i--){
            if(list.contains(i)) return false;
        }
        for(int i = 1; i<= count; i++){
            if(!list.contains(i)) return false;
        }
        return true;
    }

这段代码给了我一个无限循环。所以,我像这样更改了我的代码 -

private static boolean isPan(Long n) {
        HashSet<Integer> list = new HashSet<Integer>();
        int count = 0;
        while(n != 0){
            list.add((int) (n%10));
            count++;
            n /= 10;
        }
        for(int i = 9; i>count; i--){
            if(list.contains(i)) return false;
        }
        for(int i = 1; i<= count; i++){
            if(!list.contains(i)) return false;
        }
        return true;
    }

我刚刚改了,HashSet&lt;Long&gt;HashSet&lt;Integer&gt;list.add(n%10)list.add((int) n%10)

这给了我正确的答案,7652413。那么,谁能解释为什么 LongInteger 相比, contains 方法的工作方式不同?

【问题讨论】:

  • @pvg 我没有包含整个代码,因为只有这个方法返回错误。我不明白this is almost certainly because your parameter doesn't actually fit in an int and is truncated,因为Long 没有给我正确的答案,但Integer 可以。
  • 无论如何你都不能用 Set 做到这一点。您需要计算每个数字,而 Set 无法为您提供。当然,你根本不需要 Set,只需要一个由十个整数组成的数组。
  • @EJP 我使用 HashSet 来消除重复数字,因为我们需要一个不重复数字的 PanDigital 数字
  • 我重复一遍。如果您使用 Set,您无法计算每个数字出现的次数。您不需要消除重复的数字:您需要计数它们。如果您将它们存储在 Set 中,那么在您计算它们之前,您已经丢失了重复项。你的算法没有意义。
  • @EJP 我不需要计算一个数字出现的次数,如果您看到我的代码,我正在使用 while 循环中的 count 变量计算数字的数量。 PanDigital 意味着它必须包含从 1 到 n 的所有数字,我在我的第二个 for 循环中检查它(当有任何数字重复时返回 false)。如果 number 包含大于 n 的数字(如 7654319)返回 false,我编写了第一个 for 循环。我就是这么写的。如果您想讲述其他内容,请详细说明。

标签: java long-integer hashset


【解决方案1】:

contains(Object o) 方法对于 LongInteger 的工作方式没有什么不同。它的工作原理完全相同,即

如果此集合包含指定的元素,则返回 true。更正式地说,当且仅当此集合包含一个元素 e 使得 (o==null ? e==null : o.equals(e)) 时,才返回 true

但请注意,该方法接受 Object 作为参数类型,而不是 E。这意味着您可以使用任何类型的对象调用它。当然,E 以外的任何对象类型都会导致它返回 false,因为对于不同类型的对象,equals() 会失败(有一些例外)

所以,当您调用contains(x),而x 是一个原语时,它将根据x 的类型自动装箱,不是 关于E 的类型。所以如果xint 并且ELong,它总是会返回false

当您将Long 更改为Integer 时,不是contains() 突然起作用了。通过将传递给contains() 的值类型与集合中元素的类型正确匹配,您的代码会有所不同。


更新

你的代码效率不高:

  • 它需要一个Long作为参数,但是最大n本质上是9,并且int可以存储9位数字而不会溢出,所以使用Long,和使用拳击,是不必要的。

  • 它为每个被检查的值分配一个新的HashSet,并自动装箱找到的每个数字,加上contains()调用的9次。

相反,这可以使用位操作来完成,因为 32 位 int 值可以轻松存储 10 个布尔值(标志),指示数字是否存在。

下面的代码将建立两个位掩码foundexpected,这将指示是否找到了一个数字,以及是否应该找到一个数字。由于解决方案应该只使用数字 1-n,我们将声称数字 0 存在并且是预期的(使逻辑更简单,不必对 0 进行特殊检查)

如果一个数字出现两次(或数字 0 出现一次),另一个预期的数字将丢失,found 将不等于 expected

private static boolean isPandigital(int number) {
    int found = 1, expected = 1;
    for (int n = number; n != 0; n /= 10, expected = (expected << 1) | 1)
        found |= 1 << (n % 10);
    return (found == expected);
}

【讨论】:

  • 我不明白你的解释。我将整数传递给contains(),并且列表还包含整数,因为我正在将它们添加到list 中。所以,我没有得到你的解释。但感谢您的代码。它工作得非常快。我是初学者,所以我无法编写高效的算法。
  • @SreevathsaGowru 你说contains(i)HashSet&lt;Long&gt;list.add(n%10)HashSet&lt;Integer&gt;list.add((int) n%10) 时的工作方式不同。这是因为contains(i) 正在检查是否存在Integer,当集合元素为Long 时它总是失败,并且现在集合元素也是Integer。不是contains() 的工作方式不同,而是您的代码现在正确构建了一组Integer 元素。
【解决方案2】:

如果您希望代码正确运行,请查看listHashSet&lt;Long&gt; 的代码:

for(int i = 1; i<= count; i++){
    if(!list.contains(i)) return false;
}

您可以将变量i的类型更改为long,或将if(!list.contains(i)) return false;更改为if(!list.contains(Long.valueOf(i))) return false;

因为contains会通过元素的方法equals检查元素是否存在。在上面的代码中,变量i被自动装箱到Integer实例,因为变量i是原始@ 987654333@。 并查看整数equals

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}

但是您的list 元素的类型是Long,因此if(!list.contains(i)) return false; 行将始终返回false。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-04
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 2014-12-30
    • 1970-01-01
    相关资源
    最近更新 更多