【问题标题】:Determin the lexicographic distance between two integers确定两个整数之间的字典距离
【发布时间】:2012-11-13 08:00:18
【问题描述】:

假设我们有字典整数3,5,6,9,10,12 or 0011,0101,0110,1001,1010,1100 每个都设置了两个位。

我想要的是使用尽可能少的操作找到35 之间的距离(它们之间有多少字典排列,而不进行实际排列)。

距离表如下

3->5  = 1 or 0011->0101 = 0001
3->6  = 2 or 0011->0110 = 0010
3->9  = 3 or 0011->1001 = 0011
3->10 = 4 or 0011->1010 = 0100
3->12 = 5 or 0011->1100 = 0101

所以函数 f(3,5) 会返回 1;

该函数将始终采用相同的汉明权重(相同数量的设置位)的参数。

不应使用数组。

任何想法都会很棒。

编辑

忘了提一下,对于任何设置的位大小(汉明权重),我将始终使用第一个字典排列 (base) 作为第一个参数。

例如

hamming weight 1 base = 1
hamming weight 2 base = 3
hamming weight 3 base = 7
...

编辑 2

该解决方案应该适用于任何汉明重量,抱歉我不够具体。

【问题讨论】:

  • 不,字典上 5 在 3 之后,并设置了两个位。
  • 你忘记了数字 10 (1010)。
  • @ks6g10 Hamming 有 2 毫秒我无法编辑您的帖子,所以请修复它,谢谢!
  • 算法可以假设位长度(在您的示例中为 4)修复(这将使设置位计数算法更快)? f(5,3) 的期望结果是什么?
  • @Lewyx 位大小将从 20->30 变为 20->30,但如果在编译时可以优化某些东西,它可以更改为静态,并且 f(5,3) 也会返回 1,但我将始终如我的编辑所示使用第一个字典排列作为第一个参数。

标签: c algorithm math


【解决方案1】:

有号码
x = 2k1+2k2+...+2k
其中 k12<...>m
可以说,数字 x 在所有具有相同汉明权重的数字的字典顺序序列中的位置是
lex_order(x) = C(k1,1)+C(k2,2)+...+C(km ,m)
其中 C(n,m) = n!/m!/(n-m)!或 0 如果 m>n

例子:

3 = 20 + 21
lex_order(3) = C(0,1)+C(1,2) = 0+0 = 0

5 = 20 + 22
lex_order(5) = C(0,1)+C(2,2) = 0+1 = 1

6 = 21 + 22
lex_order(6) = C(1,1)+C(2,2) = 1+1 = 2

9 = 20 + 23
lex_order(9) = C(0,1)+C(3,2) = 0+3 = 3

【讨论】:

  • 很想用这个,但是当 m 为 20 - 30 时,无法进行排序。
  • @ks6g10 - 1
  • @EgorSkriptunoff 然后我不能真正使用数组。
  • @ks6g10 - 你的程序有什么限制?输入数值是否受某个常数的限制?您可以使用多少 ROM 大小、RAM 大小和 CPU 时间?我的解决方案可以增强为只需要 O(log(x)) 内存和 O(log^2(x)) 时间来计算 lex_order(x)。
  • @EgorSkriptunoff 我在 gpu 上做这件事,想减少内存读取量,但我会调查这是否会有任何好的结果。
【解决方案2】:

如果ab是两个set位的位置,0是最低位,a总是大于b,那么可以计算:

n = a*(a-1)/2 + b

两个值之间的距离是两个n值之间的差。

例子:

3->12:
  3:  a1=1, b1=0, n1=0
  12: a2=3, b2=2, n2=5
  answer: n2-n1 = 5

要将其扩展到其他汉明权重,您可以使用以下公式:

n = sum{i=1..m}(factorial(position[i])/(factorial(i)*factorial(position[i]-i)))

其中m 是汉明权重,position[i] 是i'th 设置位的位置,从最低有效位开始计数,最低有效设置位的位置为position[1]

【讨论】:

  • i* 应该是阶乘(i)* 吗?