我有一个大小为4,9,16或25的数组(根据输入),并且数组中的数字相同但少了一个(如果数组大小为9则是该数组中的最大元素数组将是8)数字以0开头 我想做一些算法来为数组生成某种校验和,这样我就可以比较2个数组是否相等,而不是遍历整个数组并逐个检查每个元素。
我在哪里可以获得此类信息?我需要一些尽可能简单的东西。谢谢。
编辑:只是为了清楚我想要的东西:
- 数组中的所有数字都是不同的,所以[0,1,1,2]无效,因为有一个重复的元素(1)
- 数字的位置很重要,所以[0,1,2,3]与[3,2,1,0]不一样
- 数组将包含数字0,因此也应该考虑这一点。
编辑:
好的,我试着在这里实现Fletcher的算法: http://en.wikipedia.org/wiki/Fletcher%27s_checksum#Straightforward
int fletcher(int array[], int size){
int i;
int sum1=0;
int sum2=0;
for(i=0;i<size;i++){
sum1=(sum1+array[i])%255;
sum2=(sum2+sum1)%255;
}
return (sum2 << 8) | sum1;
}
老实说我不知道返回线做了什么,但不幸的是,算法不起作用。 对于数组[2,1,3,0]和[1,3,2,0],我得到相同的校验和。
EDIT2:
好的,这是另一个,Adler校验和 http://en.wikipedia.org/wiki/Adler-32#Example_implementation
#define MOD 65521;
unsigned long adler(int array[], int size){
int i;
unsigned long a=1;
unsigned long b=0;
for(i=0;i<size;i++){
a=(a+array[i])%MOD;
b=(b+a)%MOD;
}
return (b <<16) | a;
}
这也行不通。 数组[2,0,3,1]和[1,3,0,2]生成相同的校验和。 我在这里失去了希望,任何想法?
答案 0 :(得分:4)
让我们以你的25个整数数组为例。你解释它可以包含0到24的唯一整数的任何排列。根据this page,有25个! (25个阶乘)可能的排列,即15511210043330985984000000。远远超过32位整数可以包含。
结论是,无论你多努力,你都会发生碰撞。
现在,这是一个考虑位置的简单算法:
int checksum(int[] array, int size) {
int c = 0;
for(int i = 0; i < size; i++) {
c += array[i];
c = c << 3 | c >> (32 - 3); // rotate a little
c ^= 0xFFFFFFFF; // invert just for fun
}
return c;
}
答案 1 :(得分:1)
我认为你想要的是以下主题的答案:
Fast permutation -> number -> permutation mapping algorithms
您只需获取您的排列映射到的数字,然后将其作为校验和。由于每个排列只有一个校验和,因此不能存在无碰撞的较小校验和。
答案 2 :(得分:1)
加权和的校验和怎么样?让我们以[0,1,2,3]为例。首先选择种子并限制,让我们选择种子为7并限制为10000007。
a[4] = {0, 1, 2, 3}
limit = 10000007, seed = 7
result = 0
result = ((result + a[0]) * seed) % limit = ((0 + 0) * 7)) % 10000007 = 0
result = ((result + a[1]) * seed) % limit = ((0 + 1) * 7)) % 10000007 = 7
result = ((result + a[2]) * seed) % limit = ((7 + 2) * 7)) % 10000007 = 63
result = ((result + a[3]) * seed) % limit = ((63 + 3) * 7)) % 10000007 = 462
[0,1,2,3]的校验和为462。 引用为http://www.codeabbey.com/index/wiki/checksum
答案 3 :(得分:0)
对于从1到N的N个唯一整数的数组,只需将元素相加将始终为N *(N + 1)/ 2。因此,唯一的区别在于订购。如果通过“校验和”暗示您容忍一些碰撞,那么一种方法是对连续数字之间的差异求和。因此,例如,{1,2,3,4}的delta校验和是1 + 1 + 1 = 3,但{4,3,2,1}的delta校验和是-1 + -1 + -1 = -3。
对碰撞率或计算复杂性没有要求,但如果上述情况不适合,那么我建议position dependent checksum
答案 4 :(得分:0)
根据我的理解,您的数组包含从0到N-1
的数字排列。一个有用的校验和是它的字典排序中的数组的等级。这是什么意思 ?鉴于0, 1, 2
你有可能的排列
1: 0, 1, 2
2: 0, 2, 1
3: 1, 0, 2
4: 1, 2, 0
5: 2, 0, 1
6: 2, 1, 0
校验和将是第一个数字,并在创建数组时计算。
中提出了解决方案Find the index of a given permutation in the list of permutations in lexicographic order
这可能会有所帮助,虽然看起来最好的算法是二次复杂度。要将其提高到线性复杂度,您应该事先缓存因子的值。
优势? ZERO碰撞。
编辑:计算 该值类似于多项式的求值,其中阶乘用于单项式而不是幂。所以功能是
f(x0,....,xn-1) = X0 * (0!) + X1 * (1!) + X2 * (2!) +...+ Xn-1 * (n-1!)
我们的想法是使用每个值来获得排列的子范围,并且使用足够的值来确定唯一的排列。
现在为实现(就像多项式之一):