我申请了一份工作,并被要求进行Codility测试。测试如下:
返回可被K整除的[A..B]范围内的整数数。
Args:
时间复杂度必须为O(1)。
我知道我的解决方案不是O(1),我无法想出比这更好的解决方案。 谁能开导我?
顺便说一下,它在C#中所以'int'足够大,可以容纳2000000000。public int solution(int A, int B, int K)
{
int i=0;
for(int x=A;x<=B;x++)
{
if((x % K) == 0)
i++;
}
return i;
}
答案 0 :(得分:12)
这是我在Java中的解决方案,得分100%
public int solution(int A, int B, int K) {
int count = (B/K - A/K) + (A%K == 0 ? 1 : 0);
return count;
}
答案 1 :(得分:5)
似乎(B-A) / K
加边界检查已经足够了。
修改强>:
不要只复制(B-A) / K
使用,虽然这将是骨骼结构代码,但您需要添加正确的边界检查。把它当作一种思维方式。
对于那些认为边界检查需要O(n)
的人,你错了。 O(1)足以进行边界检查。您只需要检查A / B与K的关系。
答案 2 :(得分:3)
这是稍微简化的解决方案,当A = 0时(编辑:它看起来即使在A = 0时也能正常工作,但答案结尾处的第二个版本更多)全部清除)。
首先,定义一个函数,该函数返回K除以N的数字:
在Python中:
def result_upto(n, k):
return n // k
然后答案就是result_upto(B,k) - result_upto(A - 1,k)。
编辑。让我们针对A = 0时的情况进行修复。
零可以被任何东西划分,所以我们有这样的测试用例:
// solution(A, B, K)
solution(0, 0, 1) = 1 // 0
solution(0, 1, 1) = 2 // 0, 1
solution(0, 5, 2) = 3 // 0, 2, 4
更新的功能可以是:
def result_upto(n, k):
if n >= 0:
return n // k + 1 % account for zero
else:
return 0
然后答案仍然只是result_upto(B,k) - result_upto(A - 1,k)。
答案 3 :(得分:2)
因为,我们不需要知道这些数字是什么,我们可以通过以下方式简单地找到计数:
public long solution(long low, long high, long K)
{
return (((high - low)/K) + 1);
}
例如: 0..100乘5 = 21
复杂性:O(1)
答案 4 :(得分:0)
可以是O(1)的一个衬里的解决方案是:
int boundaryCheck = (1 - (int)Math.signum(A % K)) + (1 - (int)Math.signum(B % K));
if( K < A) {
return(((B- A - 2) / K) + boundaryCheck);
}else if (K < B){
return(((B - A - 1) / K) + boundaryCheck + (1 - Math.signum((B - A)/ K)));
} else {
return(boundaryCheck);
}
我们应该考虑3例,K
答案 5 :(得分:0)
找到m1=A%K
和m2=B%K
并使用算术级数通过使用以下公式查找范围内的总数。
m1 = A%K;
m2 = B%K;
if(m1>0)
a = A + K - m1;
b = B - m2;
if(b>=a) {
total = (b-a)/K + 1;
}
else total = 0;
以上是O(1)
解决方案
答案 6 :(得分:0)
public static int solution2(int A, int B, int K)
{
return (int)Math.Floor(((B - A) % (double)K));
}
答案 7 :(得分:0)
public static void CheckDivisibility(int A,int B, int k)
{
int firstdivisorpos = A + (k- (A%k));
int lastdivisorpos = B-B%k;
int totalnosdivisble = (lastdivisorpos - firstdivisorpos)/k;
Console.WriteLine(totalnosdivisble+1);
Console.ReadKey();
}
答案 8 :(得分:0)
一种更有效的方法是简单地从A到B产生C的倍数,因此您不需要检查每个值。 C越大,效率越高。
do
{
int a = start + (C * i++);
if (a >= A && a <= B)
{
//display a;
}
if (a > B)
break;
}while (true);
答案 9 :(得分:0)
您可以使用 Java11 流 API 来解决这个问题。
public long solution(int A, int B, int K) {
return IntStream.iterate(A, n -> n <= B, n -> n+1)
.filter(n -> n%k==0)
.count();
}
使用 Java Stream API 的好处是,如果我们有一个大型数据集,我们可以使流并行以获得更好的性能。