我在HackerRank上发现了这个问题,在那里我们应该找到最小的AntiPrime数字(正整数是antiprime,当且仅当它有比任何其他小于它自身的正整数更多的除数时)。
因此,如果用户输入5,那么最小的反抵押号码将是6,因为6的除数比任何数字b / w 1到5都多。
我的方法: - 在散列集中存储每个数字1到n的除数的数量,然后从n + 1检查具有比HashSet中的除数更多的除数的整数。
public static int send(int n)
{
HashSet hs = new HashSet() ;
for(int i=1 ; i<=n ; i++)
{
hs.add(div(i)) ;
}
for(int i= n+1 ; ; i++)
{
if(Collections.max(hs).compareTo(div(i)) < 0 )
{
return i ;
}
}
}
public static int div(int n)
{
int ctr = 0 ;
for(int i=1 ; i<=n ; i++)
{
if(n % i == 0)
ctr++ ;
}
return ctr ;
}
逻辑运行完美,但在所有测试用例中它返回超时,因为我看到的复杂性是O(n ^ 2)。
所以,请建议我一个更好的算法,它可以在相对较短的时间内完成。
答案 0 :(得分:1)
您可以使用Set<>
数据结构,然后每次除数达到峰值时都可以存储(Antiprime数字)。然后,您可以调用ceiling()
之类的内容来获取该数字中的下一个最大值,因此对于5
,它会在6
时间内返回O(logn)
。此外,对于输出,使用StringBuilder
并构建结果然后输出它。对我而言,它最初与System.out.println()
无效,但结果是StringBuilder
然后是append()
。最后,在.toString()
上StringBuilder
。作为参考,我在比赛中获得了第8名(超过2000+),所以它对我有用,然后变得完美。
答案 1 :(得分:1)
我在这里引用了评论中提到的修改:
public static int send(int n)
{
HashSet hs = new HashSet() ;
for(int i=int(n/2)+1 ; i<=n ; i++)
{
hs.add(div(i)) ;
}
int markToBeat = Collections.max(hs);
for(int i=n+1 ; ; i++)
{
if(div(i) > markToBeat )
{
return i ;
}
}
}
public static int div(int n)
{
int ctr = 0 ;
for(int i=1 ; i<=sqrt(n) ; i++)
{
if(n % i == 0)
ctr++ ;
}
return ctr ;
}