Codility测试 - 在范围内找到倍数

时间:2013-12-22 20:19:04

标签: c# algorithm time-complexity

我申请了一份工作,并被要求进行Codility测试。测试如下:

返回可被K整除的[A..B]范围内的整数数。

Args:

  • A:是[0..2,000,000,000]
  • 范围内的整数
  • B:是[0..2,000,000,000]范围内的整数,A <= B
  • K:是[1..2,000,000,000]
  • 范围内的整数

时间复杂度必须为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;
}

10 个答案:

答案 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加边界检查已经足够了。


修改

  1. 不要只复制(B-A) / K使用,虽然这将是骨骼结构代码,但您需要添加正确的边界检查。把它当作一种思维方式。

  2. 对于那些认为边界检查需要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

  1. 如果A不能被K分割,则符号为1表示我们不应该将数字增加1(所以我们按1-1计算)

答案 5 :(得分:0)

找到m1=A%Km2=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 的好处是,如果我们有一个大型数据集,我们可以使流并行以获得更好的性能。