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

optimize code to get the number of integers within given range that are divisible by integer

本文关键字:整数 数数 范围内 代码 获取 优化      更新时间:2023-10-16

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

我知道做到这一点的简单方法是在整个范围内循环

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

计数器掌握着答案。

但是这对于大范围来说非常慢。 例如 x=0 和 y=3,000,000,000。

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

非常感谢。

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

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

负值的更新:以下内容适用于 s 和 e 类型范围内的任何值,前提是 s <= e 和 0 <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,除法修改为四舍五入到 -无穷大而不是朝零(因此 -1/10 产生 -1 而不是 0(。

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

解释:

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

因此(floor((high/d( - (floor((low/d(将给出可在范围(低,高(中整除的数字(请注意,低被排除,高被包含在这个范围内(

现在要从范围内删除高,只需减去(高%d==0(

使用 fmodf 作为浮点数。

只有这个实现对我有用([0..2kkk]中的 A、B ;K in [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;
}

与其遍历每个数字,不如尝试

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;
}

并且仅使用除数的倍数。现在你不是在做重复除法(慢(,而是在做重复乘法(更快(。

我很

确定你可以这样做:

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

您要求计算 x 和 y 之间可被 n 整除的整数数(x 和 y 都包含在范围内(。不需要任何循环,只需要两个除法来计算答案。让我们考虑一个简单的例子:对于 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 = 14。但是当其中一个端点被除数除法时要小心;我会把它留给你来制定细节,并编写程序。

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

找到从 R1 开始的最小数,可被 n 整除。称之为小数。

找到从 R2 开始的最大数字,可被 n 整除。称之为大数。

可整除的总数=(大-小(/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);
}
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;
}
 public int myfunc(int low, int high, int test) {   
    int count = 0;
    if(low % test == 0)
       count++;
    count +=(high-low)/test;
    return count;
 }

好吧,我不是大学教授,所以我没有为你准备一些惊人的公式,但实际上据我所知,检查这样的数字列表的唯一方法是迭代它们,最后你将不得不计算变量以检查它是否可整除, 现在有一种方法可以优化您的算法,首先对数字进行排序!这最初会很昂贵,但任何连续需要检查数字都会快得多,

我建议看看排序算法,我会使用的算法是气泡排序,它会在谷歌上出现很多。

至于你可以用排序做什么,你可以将数字分类为倍数列表,例如 2 4 6 8 都是 2 的倍数,所以你基本上可以检查列表中的第一个,其余的将立即知道也是可整除的

请记住,可能有一种更有效的方法可以做到这一点,只需提供我的 2 美分