Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/react-native/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 在O(n)时间和O(1)空间中生成数组的随机置换_Algorithm_Random_Probability Theory - Fatal编程技术网

Algorithm 在O(n)时间和O(1)空间中生成数组的随机置换

Algorithm 在O(n)时间和O(1)空间中生成数组的随机置换,algorithm,random,probability-theory,Algorithm,Random,Probability Theory,我们必须在O(1)空间中生成数组{1,2,3,…,n}。 我可以在O(n)空间中完成它 我做了O(n)空间解决方案,首先存储数组,然后将其随机化。但是,如何在不将数组存储在O(1)空间的情况下执行此操作 我只是生成随机数,而不是存储它们,我需要打印它们,因为存储需要O(n)空间,但我需要在O(1)空间中进行,我的疑问是,如果我们继续生成随机数并打印它们,可能会有一些介于1到n之间的数,可能会多次生成,而有些可能不会生成。那么,如何在O(1)空间中精确打印所有数字一次呢 附言-我没有得到任何数组。

我们必须在
O(1)
空间中生成数组
{1,2,3,…,n}

我可以在
O(n)
空间中完成它

我做了
O(n)
空间解决方案,首先存储数组,然后将其随机化。但是,如何在不将数组存储在
O(1)
空间的情况下执行此操作

我只是生成随机数,而不是存储它们,我需要打印它们,因为存储需要O(n)空间,但我需要在O(1)空间中进行,我的疑问是,如果我们继续生成随机数并打印它们,可能会有一些介于1到n之间的数,可能会多次生成,而有些可能不会生成。那么,如何在O(1)空间中精确打印所有数字一次呢


附言-我没有得到任何数组。输入只是'n',我必须在O(n)时间和O(1)空间中打印数组{1,2,3,…,n}的排列。

如果n是2的幂,可以使用块大小为n位的分组密码在n个元素上生成排列-只需写出Encrypt(0),Encrypt(1)。。。加密(n-1)

如果n不是2的幂,则m是n以上2的第一次幂。加密0..n-1,如果结果>=n,则再次加密,直到得到范围内的值。这相当于将m个元素的排列作为一个循环写出,然后删除>=n的元素


如果没有所需大小的标准分组密码,可以使用Luby Rackoff aka Feistel构造,使用哈希函数作为中的F操作来创建一个。Feistel网络的一个特点是,F()产生一个以上的位,被视为置换,它们从不产生奇数置换:如果Feistel输出为k位宽,则每轮产生2^(k-1)2个循环的倍数,这会产生k>1的偶数置换,因此,您可能需要考虑一下这一点和/或使用具有不同反馈风格的多个Feistel回合,从中获得合理的随机排列。一个具有1位Feistel输出的Fiestel循环系统可以被视为交换网络的隐式结构,可用于在网络中实现任意排列。

一般来说,这是一个不可能的问题。虽然可以在列表之外没有任何内存的情况下重新组织列表,并留下统计上随机的列表,但真正的随机列表是不可能的

如果问题被解释为数字流过滤器,那么在任何时间点,我们只能看到流的一个元素。这有助于我们看到流中尚未处理的部分,但如果我们无法更改该部分,我们就会陷入困境

完美混合列表的两种基本方法(给定一个完美的随机数生成器):


一个真正的随机列表可以简化为这两种方法之一。不幸的是,这两种方法都不能与没有随机写入权限的单通过滤器一起使用。第一个需要修改列表中尚未创建的部分。第二个需要修改已经打印出来的列表的一部分。

严格地说,
O(1)
解决方案是不可能的,因为数字
n
本身需要
log(n)
位来存储


另一方面,如果练习的目标是避免使用
n
整数数组,并且您愿意牺牲一些严格性-即假设
n可以在
O(1)
内存中表示-解决方案是在
k范围内生成一个随机数
[0,n!)
,并在计算时打印数字。

我已经构建了一个线性反馈移位寄存器生成器解决方案,我认为它满足您的要求。该实现基于斐波那契LFSRs,因此它可以实现给定位数的全周期。我继续输入多项式系数,最多为19位,并根据指定的
N
值选择适当的系数集。大于
N
的生成值会被夹住,但整个循环中的值总数小于
2N
,因此它将在
O(N)中生成
N
time。LFSR保留一个状态字,因此它是
O(1)
space

以下是Ruby中的实现:

#!/usr/bin/env ruby -w

# Linear Feedback Shift Register generator which operates on smallest bit
# range possible for a specified integer range, and skips over values outside
# the specified range. Since this attains full cycle length for the specified
# number of bits, and the number of bits is minimized relative to the specified
# N, the total number of iterations is bounded by 2N and is therefore O(N).
class LFSR
  # Polynomials for maximal LFSRs determine shift amounts for up to 19 bits.
  # See https://en.wikipedia.org/wiki/Linear_feedback_shift_register for
  # details. Add more entries if you need more than 19 bits.
  SHIFT_AMT = [
    [], [], [1], [1], [1], [2], [1], [1], [2, 3, 4], [4], [3], [2],
    [1, 2, 8], [1, 2, 5], [1, 2, 12], [1], [2, 3, 5], [3], [7], [1, 2, 5]
  ]

  # Constructor for the LFSR.  Specify the N and seed value.
  def initialize(n, seed)
    @n = n
    @state =  (seed % n) + 1
    @num_bits = Math.log2(n).floor + 1
  end

  # Generate the next iterate of the LFSR.  If it's above the specified N,
  # keep trying until you're done.
  def next_value
    loop do
      bit = @state
      SHIFT_AMT[@num_bits].each { |amt| bit ^= (@state >> amt) }
      @state = ((@state >> 1) | ((bit & 1) << (@num_bits - 1)))
      return @state if @state <= @n
    end
  end
end

N = (ARGV.shift || 100).to_i # Specify the 'N' value on cmd line. Default = 100
SEED = (ARGV.shift || 0x7FFF).to_i # Optionally specify a "seed" for the LFSR
my_lfsr = LFSR.new(N, SEED)  # Instantiate an LFSR object
N.times { p my_lfsr.next_value }   # Invoke it N times, print the results
!/usr/bin/env ruby-w
#最小位线性反馈移位寄存器发生器
#指定整数范围的可能范围,并跳过外部的值
#指定的范围。因为这达到了指定范围的完整循环长度
#位数,并且相对于指定的
#N,总迭代次数以2N为界,因此为O(N)。
类LFSR
#最大LFSR的多项式可确定多达19位的移位量。
#看https://en.wikipedia.org/wiki/Linear_feedback_shift_register 对于
#详细信息。如果需要超过19位,请添加更多条目。
班次金额=[
[], [], [1], [1], [1], [2], [1], [1], [2, 3, 4], [4], [3], [2],
[1, 2, 8], [1, 2, 5], [1, 2, 12], [1], [2, 3, 5], [3], [7], [1, 2, 5]
]
#LFSR的构造函数。指定N和种子值。
def初始化(n,种子)
@n=n
@状态=(种子%n)+1
@num_bits=Math.log2(n).floor+1
结束
#生成LFSR的下一次迭代。如果它高于指定的N,
#继续努力,直到完成为止。
def next_值
环道
位=@状态
SHIFT_AMT[@num_bits]。每个{AMT|bit^=(@state>>AMT)}

@state=(@state>>1)|((bit&1)在一个相当自然的模型中是不可能的。如果给你一个数组,你需要对它进行洗牌,那么可以使用。根据定义,从头开始生成一个没有额外空间的数组是不可能的,因为输出本身是
O(n)
,你需要生成它。O(1)空间需求当然与额外存储有关。使用O(1)sp没有解决方案
#!/usr/bin/env ruby -w

# Linear Feedback Shift Register generator which operates on smallest bit
# range possible for a specified integer range, and skips over values outside
# the specified range. Since this attains full cycle length for the specified
# number of bits, and the number of bits is minimized relative to the specified
# N, the total number of iterations is bounded by 2N and is therefore O(N).
class LFSR
  # Polynomials for maximal LFSRs determine shift amounts for up to 19 bits.
  # See https://en.wikipedia.org/wiki/Linear_feedback_shift_register for
  # details. Add more entries if you need more than 19 bits.
  SHIFT_AMT = [
    [], [], [1], [1], [1], [2], [1], [1], [2, 3, 4], [4], [3], [2],
    [1, 2, 8], [1, 2, 5], [1, 2, 12], [1], [2, 3, 5], [3], [7], [1, 2, 5]
  ]

  # Constructor for the LFSR.  Specify the N and seed value.
  def initialize(n, seed)
    @n = n
    @state =  (seed % n) + 1
    @num_bits = Math.log2(n).floor + 1
  end

  # Generate the next iterate of the LFSR.  If it's above the specified N,
  # keep trying until you're done.
  def next_value
    loop do
      bit = @state
      SHIFT_AMT[@num_bits].each { |amt| bit ^= (@state >> amt) }
      @state = ((@state >> 1) | ((bit & 1) << (@num_bits - 1)))
      return @state if @state <= @n
    end
  end
end

N = (ARGV.shift || 100).to_i # Specify the 'N' value on cmd line. Default = 100
SEED = (ARGV.shift || 0x7FFF).to_i # Optionally specify a "seed" for the LFSR
my_lfsr = LFSR.new(N, SEED)  # Instantiate an LFSR object
N.times { p my_lfsr.next_value }   # Invoke it N times, print the results