优化代码以获取给定范围内可被整数整除的整数数
optimize code to get the number of integers within given range that are divisible by integer
给定范围 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/d
和 s = (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 美分
- 如何初始化整数+字符串数组
- 整数指针数组的元素是否可以指向整数数组?
- 整数指针数组的大小
- 将整数输入数组的方法比 scanf() 或 cin 更快?
- 将字符 2d 数组转换为整数 2d 数组
- 取消随机排列整数/字符数组
- 用于存储原子整数的数组
- 在 C++ 中使用 10 个随机整数的数组进行气泡排序不起作用
- 指向整数 C++ 数组的指针
- 从矢量<对<双*,对<双*,整数*>>到数组的可视化C++转换
- 设置整数等于数组中的值数量
- 计算每个连续的整数在数组中总和
- 从文件中读取整数到数组
- 创建字符指针和整数指针数组
- 使用 const 整数声明数组
- 创建整数 2d 数组(与字符串 2d 数组相比),而不提及维度
- 发送 2 个整数的数组作为参数
- 如何在向量内的结构内打印指向整数的数组
- C++:使用 STL 排序对不同列上的整数 2d 数组进行排序的时间复杂度
- 对1000个整数的数组进行排序