生成随机序列的整数相差1位而不重复

时间:2011-06-11 18:44:04

标签: algorithm random

我需要生成一个N位整数的(伪)随机序列,其中连续的整数与前一个整数的差别仅为1位,并且序列永远不会重复。我知道格雷码会产生只有1位差异的非重复序列,而LFSR会产生非重复的随机序列,但我不知道如何将这些想法结合起来产生我想要的东西。

实际上,N会非常大,比如1000.我想随机抽取2 ^ 1000个整数的大空间,但是我需要生成类似随机游走的东西,因为应用程序只能从一个数字跳到翻过一下。

3 个答案:

答案 0 :(得分:5)

使用任意随机数生成器算法生成1到N之间的整数(或0到N-1,具体取决于语言)。使用结果确定要翻转的位的索引。

为了满足随机性,您需要存储以前生成的数字(感谢ShreevatsaR)。此外,您可能会遇到无法获得非重复答案的情况,因此这也需要回溯算法。

答案 1 :(得分:1)

这让我想到了分形 - 遵循朱莉娅集合中的边界或沿着那些线条的东西。

如果N为1000,则使用2 ^ 500 x 2 ^ 500分形位图(显然不提前生成它 - 您可以按需派生每个像素,并且大多数不需要)。每个像素移动是跟随像素之间的边界线的上,下,左或右一个像素,如简单的位图跟踪算法。只要你从位图的边缘开始,你应该迟早返回到位图的边缘 - 如果你看一下无界,那么在特定的“颜色”边界之后应该总是给出一个没有自交的闭合曲线。该分形的版本。

位图的x和y轴当然需要“格雷编码”坐标 - 有点像超大的卡诺图。跟踪中的每个步骤(向上,向下,向左或向右一个像素)等于一个位图坐标中的单个位更改,因此在随机游走中的结果值的一位中。

修改

我刚才意识到有问题。边界越皱纹,您越有可能在追踪中找到可以选择方向的点,例如......

 * | .
---+---
 . | *

无论您进入这一点,您都可以选择三种方式。选择其他两个错误的一个,你可能会回到这一点,因此这是一个可能的自交点并可能重复。您可以消除继续在同一方向的选择 - 无论您转向哪种方式都应该在追踪时保持边界路径左右两侧的相同边界颜色 - 但这仍然可以选择两个方向。

认为可以通过在分形中至少有三种颜色,并始终保持相同颜色到边界的一个特定边(相对于轨迹方向)来消除问题。但是,可能存在“只要分形不太皱”的附带条件。

最后的解决方法是保留此选项可用的点数记录。如果你回到同一点,回溯并采取另一种选择。

答案 2 :(得分:0)

虽然是这样的算法:

seed()
i = random(0, n)
repeat:
    i ^= >> (i % bitlen)
    yield i

...会返回一个随机的整数序列,每个整数相差1位,它需要一个巨大的数组来进行回溯以确保数字的唯一性。 此外,随着回溯密度的增加,您的运行时间将呈指数级增长(?),因为按顺序中的每个数字命中新的非重复数字的机会会减少。

为了减少时间和空间,可以尝试合并其中之一:

Bloom Filter

使用布隆过滤器大幅减少唯一性回溯所需的空间(和时间)。

由于布隆过滤器具有不时产生误报的缺点,因此错误检测到一定比率的重复(sic!)(因此被跳过)你的序列会发生。

虽然使用布隆过滤器会减少空间和时间,但您的运行时间仍会呈指数级增长(?)......

Hilbert Curve

希尔伯特曲线表示在二次平面(或立方体)上的非重复(一种伪随机)步行,每步长度为1 。
使用 Hilbert曲线(在适当的值分布上),人们可以完全摆脱对回溯的需求。 要使序列获得种子,您需要生成nn作为您的平面/立方体/超立方体的维度)0和s之间的随机数(s是飞机/立方体/超立方体两侧的长度)。 希尔伯特曲线不仅不需要回溯,它还会使序列运算符以每个数字O(1)运行(与使用回溯相比,这将使您的运行时间随着时间的推移呈指数增长(?)...)
为了对你的序列进行播种,你需要通过每个n维度中的随机位移来换行n - 维分布。


Ps:你可能会在这里得到更好的答案:CSTheory @ StackExchange (或不是,见评论)