我有一个M个整数数组。我必须找到所有可能的整数K(假设至少有1 K),这样:
1) K > 1
2) arr[0]%K = arr[1]%K = arr[2]%K = ... = arr[M-1]%K
这个问题的最佳算法是什么?
答案 0 :(得分:3)
K
,我们知道,例如,数组arr
,arr[0]=4; arr[1]=6; arr[2]=9
是无效的,因为没有模数给出了相同的结果。K
> 1,我们知道数组的所有值都不能相同。但是,对于所有modK
,它们都是K
。请注意,arr[i]%K
(对于任何0=<i<M
}并非必须是正面的。
代码尚未经过测试
在我看来,确定K
值的最简单方法是找出数组中每个值之间的差异。 (我将在Java中展示示例。)让我们说arrDiff
包含每个值的差异,以便
arrDiff[0] = arr[0]-arr[1];
arrDiff[1] = arr[1] - arr[2];
...
arrDiff[M-1] = arr[M-1] - arr[0];
现在,找到G = gcd(arrDiff[0],arrDiff[1],...,arrDiff[M-1]
以查找所有有效的K
。您可以使用任何gcd
方法,即Euclidean Algorithm,以便迭代/递归查找
G
。您也可以忽略负面差异,因为gcd
会给您带来积极的结果。
[All of G's factors]>1
(包括G
本身)将是有效的K
值。
我不打算做证明(我会留给你),但为了清楚起见,我们举个例子。
arr
//Let's do an easy one with M=3
int arr[] = new int[3];
arr[0] = -7;
arr[1] = 9;
arr[2] = 25
我会在这里展示一个稍微高效的实现(感谢@RBarryYoung)。
int min = findSmallestNumber(arr); //Returns min value (may be negative)
//The array size is intended to not include the minimum, assuming we have no duplicates.
int arrDiff[] = new int[arr.length-1];
for(int num : arr){
if(num==min) continue;
arrDiff[num] = arr[num] - min;
}
对于上面的示例,此代码应在16,32
中为我们提供arrDiff
的值。请注意,使用此方法应在下一步中为gcd计算生成所有正值。
G = gcd
我不会为你写一个gcd方法,因为有很多实现;我假设你有一个方法int gcd(int a, int b)
。
int g = gcd(arrDiff[0], arrDiff[1]);
for(int i = 2, i < arrDiff.length-1, i++){
g = gcd(g, arrDiff[i]);
}
//return g;
请注意,如果我们在数组中只有两个值,则不需要使用gcd
- 只需使用单个差异。
对于我们的例子,你可以很容易地发现gcd(-16,-16,32)= gcd(16,16,32)= 16。因此,16及其所有因子> 1应该是答案。至少让我们检查16。请注意以下&#34; =&#34;应该是一个同余符号(三个条不是两个)。
-7mod16 = 9mod16
9mod16 = 9mod16
25mod16 = 9mod16
您可以检查这是否也适用于因素2,4,8
。 (对于所有这些因素,您应该获得1mod8 => 1mod4 => 1mod2
。)
如果您必须在代码中找到这些因素,您可能会对factoring algorithms中的一个感兴趣,以查找G
的所有因子大于1.挑选最优化的因素可能取决于您的数据
因此,它实际上是您可能需要的算法组合。我上面展示的内容可能会稍微快一些,但基本算法现在应该是平易近人的。
答案 1 :(得分:0)
#include <stdio.h>
int GCD(int a, int b) {
while(a!=b) {
if(a>b) a-=b; else b-=a;
}
return a;
}
int main()
{
int n; scanf("%d",&n);
int a[n],i,j;
for(i=0;i<n;i++) {
scanf("%d",&a[i]);
}
//finding minimum
int min=a[0]; for(i=0;i<n;i++) if(min>a[i]) min=a[i];
//finding differences and storing except minimum
int diff[n-1]; for(i=0,j=0;i<n;i++) if(a[i]!=min) diff[j++]=a[i]-min;
// if n is 2, we have only diff[1], otherwise we can follow algo
int g=(n==2)?diff[0]:GCD(diff[0],diff[1]); for(i=2;i<n-1;i++) g=GCD(g,diff[i]);
//finding divisors of the final gcd.
for(i=2;i<=g;i++) if(g%i==0)printf("%d ",i);
return 0;
}
答案 2 :(得分:0)
这是我解决该问题的代码
n = int(input("how many numbers to guess? (normally 4)"))
att = int(input("how many attempts? (normally 10)"))
count = 0
pul = {} # here're your previous lists, currently empty
while count < att:
ul = [int(input()) for i in range(n)]
pul[count] = ul # you can use more flexible key value, as you mentioned
count = count + 1
# if you need to replay lists - you just use your "pul" dict
for i in range(count):
print(f'your № {i} list was {pul.get(i)}')