优化代码以获得给定范围内可被整数整除的整数数

时间:2012-08-04 00:45:56

标签: java c++ math division

给定范围x,y。我需要计算中间的所有数字,并且可以被n整除。

我知道这样做的简单方法是循环遍及整个范围

for(int i=x;i<=y;i++) if(i%n ==0) counter++; 

计数器得到答案。

但是这对于大范围来说效果很慢。例如x = 0,y = 3,000,000,000。

我确信我可以使用一些关系来减少迭代次数并优化此代码以提高速度。我搜索但我找不到它。任何人都可以帮助我。

非常感谢。

10 个答案:

答案 0 :(得分:7)

这有效:(e+1 - s) / d + (e%d < (s+d-1)%d)。 (它使用C语义和整数运算,并假设开始是非负的.s是起始值,e是结束值[包含],d是除数。)

更新:更好的解决方案是e/d - (s-1)/d。这是受User448810的启发。这要求是积极的;处理零或负s(或e)需要调整截断为零(我们希望这个问题的负无穷大)。

负值更新:如果s&lt; = e和0&lt; d:

e = e <  0 ? (e+1)/d - 1 : e/d;
s = s <= 0 ? s/d - 1 : (s-1)/d;
return e-s;

基本上,前两个语句相当于e = e/ds = (s-1)/d,其中除法被修改为向-infinity而不是向零舍入(因此-1/10产生-1而不是0)

答案 1 :(得分:2)

(floor)(high/d) - (floor)(low/d) - (high%d==0)

<强>解释

有一个/ d数字可以从0到a整除。 (d!= 0)

因此(地板)(高/ d) - (地板)(低/ d)将给出在该范围内可分割的数字(低,高)(注意低排除,高包含在此范围内)

现在要从范围中删除高刚刚减去(高%d == 0)

使用fmodf作为花车。

答案 2 :(得分:0)

只有这个实现对我有效(A,B在[0..2kkk]; K在[1..2kkk]):

function solution(A, B, K) {
    if(B < K) return A === 0 ? 1 : 0;
    if(A === B) return A % K === 0 ? 1 : 0;

    var pre = A === 0 ? 2 : 1;
    var min = A < K ? K : A + A % K;
    var max = B - B % K;

    return (max - min) / K + pre;
}

答案 3 :(得分:-1)

我很确定你能做到这一点:

public static int numDivisible(int low, int high, int test) {
    return (high-low)/test;
}

你去吧。一个恒定时间的解决方案。由于您不需要确切地知道哪些数字可以被整除,因此您不需要费力迭代所有这些数字。

编辑:根据@ Chaser324将此更改为以下内容。

public static float numDivisible(float low, float high, float test) {
    return Math.ceil((high-low)/test);
}

编辑:一个小错字,即。{,text更改为test

答案 4 :(得分:-1)

您可以尝试

,而不是遍历每个数字
public int test(int floor, int ceil, int n) {
    int a = (floor / n) + 1;
    int counter = 0;
    while (a * n <= ceil) {
        counter++;
        a++;
    }
    return counter;
}

并且仅使用除数的倍数。现在你没有重复分裂(慢),你正在重复乘法(更快)。

答案 5 :(得分:-1)

public static int solution(int low,int high, int n) {
    boolean h0=high%n==0;
    boolean l0=low%n==0;

    int k1=l0?low/n:(low+n-low%n)/n;
    int k2=h0?high/n:(high+n-high%n)/n;

    //                 |-----------|
    // ---------------k1----------k2---------------

    if(k2*n>high) k2--;

    return k2-k1+1;

}

答案 6 :(得分:-1)

您要求计算x和y之间的整数数(x和y都包含在范围内),这些整数可以被n整除。不需要任何循环,只需要两个分区来计算答案。让我们考虑一个简单的例子:对于100到200的范围,有多少整数可以被7整除?

从范围的低端开始:100/7 = 14,余数为2.现在除数7减去剩余的2是5,因此可被7整除的范围内的最小数字是100 + 5 = 105。

现在转到范围的高端:200/7 = 28,余数为4,因此可被7整除的范围内的最大数字是200 - 4 = 196。

因此,可被7整除的范围内的数字分别为105,112,119,126,133,140,​​147,154,161,168,175,182,189和196。其中有14个,您可以通过几种方式计算出来。取两端的商并减去它们:28 - 14 = 14.或者取两个端点的差值,除以除数,然后加1:196 - 105 = 91,91 / 7 = 13,13 + 1 =但是当其中一个终点被除数除掉时要小心;我会留给你详细说明,也可以编写程序。

答案 7 :(得分:-1)

请提供以下算法的评论:假设范围是[R1,R2],要划分的数字是n。

找到从R1整除的最小数字,将其整除。调用它。

找到从R2整除的最大数字。把它称之为大。

可分割的总数=(大 - 小)/ n + 1.

最坏的情况仍然是O(n),但对于R1和R2之间的巨大差异可能是有效的。我已经覆盖了所有情况。请建议。

int numofDivisible(int R1, int R2, int n) {

int small = R1, large= R2;

if ((R1 > R2) || (n==0)) return 0;

if (R1 == R2) {
    if (R1 % n == 0) 
        return 1;
    else 
        return 0;
}

while(small <= R2){

     if(small % n == 0)
         break;

      ++small;
}

if (small > R2)
    return 0;


while (large > small) {

    if (large % n == 0)
       break;

    --large;
}

if (large == small)
   return 1;

return ((large-small)/n + 1);

}

答案 8 :(得分:-1)

 public int myfunc(int low, int high, int test) {   
    int count = 0;
    if(low % test == 0)
       count++;
    count +=(high-low)/test;
    return count;
 }

答案 9 :(得分:-2)

好吧,我不是大学教授,所以我没有为你提供一些惊人的公式,但实际上我知道检查一个数字列表的唯一方法是迭代它们,在最后你必须评估变量以检查它是否可分,现在有一种方法来优化你的算法,首先对数字进行排序!这最初会很昂贵,但任何连续检查数字的需求都会快得多,

我建议查看排序算法,我会使用的是冒泡排序,这将在谷歌上发布。

至于你可以对排序做什么,你可以将数字排序成多个列表,例如2 4 6 8都是2的倍数,所以你基本上可以检查列表中的第一个,其余的将是即刻已知也可分割

请记住,这可能是一种更有效的方法,只需提供2美分