繁体   English   中英

Java HashSet(长整数对整数)

[英]Java HashSet (Long vs Integer)

我正在解决这个问题,(来自Euler项目的41),我注意到其中的HashSet方法在Long方面的工作方式与Integer相比有所不同(我在这里可能是错误的,请纠正我)。

问题是 -

我们可以说,如果n位数字恰好一次使用了1到n的所有数字,那么它就是pandigital。 例如,2143是一个4位数的全数字,并且也是质数。

存在的最大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<Long>更改为HashSet<Integer>并将list.add(n%10)更改为list.add((int) n%10)

这给了我正确的答案,7652413。那么,谁能解释为什么与Integer相比,contains方法对Long作用不同?

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

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

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

因此,当您调用contains(x) ,并且x基元时 ,它将根据x的类型而不是 E的类型自动装箱。 因此,如果xintELong ,则它将始终返回false

当将Long更改为Integer时,它的contains()不会突然有所不同。 通过正确地将传递给contains()的值的类型与集合中元素的类型进行匹配,可以使您的代码有所不同。


UPDATE

您的代码效率不高:

  • 它使用Long作为参数,但是max 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);
}

如果您希望代码正确运行,请参见listHashSet<Long>代码:

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是基本int 并看到整数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。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM