[英]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
作用不同?
对于Long
与Integer
contains(Object o)
方法没有什么不同。 它的工作原理完全相同,即
如果此集合包含指定的元素,则返回
true
。 更正式地说,当且仅当此集合包含元素e
使得(o == null?e == null:o.equals(e))时,才返回true
。
但是请注意,该方法接受Object
作为参数类型,而不是E
这意味着您可以使用任何类型的对象来调用它。 当然,除E
之外的任何对象类型都将导致它返回false
,因为对于不同类型的对象, equals()
会失败(有一些例外) 。
因此,当您调用contains(x)
,并且x
是基元时 ,它将根据x
的类型而不是 E
的类型自动装箱。 因此,如果x
为int
且E
为Long
,则它将始终返回false
。
当将Long
更改为Integer
时,它的contains()
不会突然有所不同。 通过正确地将传递给contains()
的值的类型与集合中元素的类型进行匹配,可以使您的代码有所不同。
UPDATE
您的代码效率不高:
它使用Long
作为参数,但是max n
本质上是9
,并且int
可以存储9位数字而不会溢出,因此不需要使用Long
和装箱。
它为每个要检查的值分配一个新的HashSet
,并自动装箱找到的每个数字,并为contains()
调用加上9次。
取而代之的是,这可以使用位操作来完成,因为32位int
值可以轻松存储10个布尔值(标志),指示是否存在数字。
下面的代码将建立两个位掩码, found
和expected
,这将表明一个数字是否被发现,和一个数字是否应该被发现。 由于解决方案仅应使用数字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);
}
如果您希望代码正确运行,请参见list
为HashSet<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.