我正在解决这个问题,(来自Project Euler的41个),我注意到,与Integer相比,包含HashSet的方法对于Long的工作方式不同(我可能在这里错了,请纠正我,如果我的话)。
问题是 -
如果使用的话,我们会说n位数是pandigital 所有数字1到n恰好一次。例如,2143是4位数 pandigital也是主要的。
存在的最大n位数pandigital素数是什么?
我检查号码是否为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。那么,有人可以解释为什么与Long
相比,包含方法对Integer
的工作方式有所不同吗?
答案 0 :(得分:3)
contains(Object o)
方法对Long
与Integer
的工作方式不同。它完全相同,即
如果此set包含指定的元素,则返回
true
。更正式的是,当且仅当此集合包含元素true
时才返回e
(o == null?e == null:o.equals(e))。
请注意,该方法接受Object
作为参数类型,而不是E
。这意味着您可以使用任何类型的对象调用它。当然,E
以外的任何对象类型都会导致它返回false
,因为equals()
对于不同类型的对象(有一些例外)会失败。
因此,当您致电contains(x)
,而x
是原语时,它会根据x
的类型自动装箱,<对于E
的类型,em> not 。因此,如果x
是int
且E
是Long
,则它始终会返回false
。
当您将contains()
更改为Long
时,突然有效的Integer
不是contains()
。通过将传递给Long
的值的类型与集合中的元素类型正确匹配,您的代码可以有所不同。
<强>更新强>
您的代码效率不高:
它需要n
作为参数,但最高9
本质上是int
,并且Long
可以存储9位数而不会溢出,所以不需要使用HashSet
和使用拳击。
它为每个被检查的值分配一个新的contains()
,并自动检测找到的每个数字,加上int
次调用的9次。
相反,这可以使用位操作来完成,因为32位found
值可以轻松存储10个布尔值(标志),指示是否存在数字。
下面的代码将建立两个位掩码expected
和found
,它们将指示是否找到一个数字,以及是否应该找到一个数字。由于解决方案应仅使用数字1-n,我们将声明数字0存在并且预期(使逻辑更简单,无需对0进行特殊检查)。
如果一个数字出现两次(或数字0出现一次),则另一个预期数字将丢失,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);
}
。
{{1}}
答案 1 :(得分:0)
如果您希望代码正常运行,请查看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。