【问题标题】:Given a permutation function, find the number of repetition required to get the original input给定一个置换函数,求得到原始输入所需的重复次数
【发布时间】:2015-08-01 09:02:11
【问题描述】:

输入:一个字符数组和一个置换函数 P。函数 P 以某种确定性的方式对输入进行混洗。例如,如果 P 是(向右推)

1234 -> P -> 4123 -> P -> 3412 -> P -> 2341 -> 1234

在上面的例子中,对一个输入应用 P 四次 次会给你一个输入。 P可以是恒等映射,即require重复为1

1234 -> P -> 1234

P 可以看作是某种映射函数,它最终会打乱输入,P 的输出需要是原始输入的一个排列。 P 可能很复杂,比如交换赔率和偶数;接下来,交换第一个和最后一个,依此类推。

你的工作就是写一个函数,比如说,

public static char[] P(char[] arr) {...} # the content is unknown
public static int getNumRequired(char[] arr) {
  // your code here
}

显然,有一个蛮力解决方案 - 通过创建一个 while 循环,我们计算循环数,然后在满足条件时中断循环。这里的问题是:“我们能比蛮力做得更好吗?”

有人告诉我,有一种有效的方法(或更好的方法)来计算需要重复的次数以获得原始输入。

【问题讨论】:

  • 这取决于您拥有的置换函数的种类。如果这些是加密哈希函数,那将很难。同样重要的是您要执行哪种设置?一次性反转?多次反转(许多不同的输入值)?在后一种情况下,Rainbow tables 的技术可能是合适的。这些可能对您有用,即使这些只是空间/时间权衡(复杂性没有变化!)
  • 是否假设函数应用的排列不依赖于输入中的具体值?
  • 是的,函数 P 不依赖于输入值。 P 是给定的,不会改变 w.r.t 输入。如果提供了 P 和 arr,我们的目标是计算出所需的重复次数。

标签: algorithm dynamic-programming


【解决方案1】:

基本思想:考虑排列列表中每个数字的移动。它将形成一个具有特定长度的循环。每个数字形成的循环可以是0 - (n-1)范围内不同长度的循环。然后当所有循环相遇时,整个排列将重复,这将与循环长度的 LCM(最小公倍数)相同。

以算法的方式:

  1. 对于每个数字,找出您得到相同数字之前的排列数。在给定的示例中,对于1,它是:1->4->3->2->1,所以排列的数量是4

  2. 获取上述所有排列的 LCM(最小公倍数)。这将是您寻找的数字。

在上面的例子中:

1->4->3->2->1 ==> 4
2->1->4->3->2 ==> 4
3->2->1->4->3 ==> 4
4->3->2->1->4 ==> 4
and
LCM(4, 4, 4, 4) = 4

蛮力可能需要高达O(n!) 的复杂性。上面每个数字最多会有O(n),因此整体复杂度是O(n^2) + <complexity of getting LCM>

注意:我认为获得两个数字的 LCM 的复杂性与获得两个数字的 GCD 相同。一旦我弄清楚计算,我会更新结果。

计算 N 个数的 LCM 的复杂性: 例如,我们有 4 个数字 a、b、c、d:

LCM(a, b, c, d) = a*b*c*d / GCD(abc, abd, acd, bcd)

GCD (abc, abd, acd, bcd) = GCD(abc, GCD(abd, GCD(acd, bcd)))

还可以在O(log(x) + log(y)) 时间计算GCD(x,y)

在最坏的情况下,我们需要计算LCM(1, 2, ..., n-1, n)。这将导致计算GCD(n!/1, GCD(n!/2, GCD(n!/3, ..., GCD(n!/(n-1), n!/n))))。这将具有O(log(n!/1), log(n!/2) + ... + log(n!/n)) 的复杂度,与O((n-1) * log(n!))O(n^2 * log(n)) 相同

因此上述方法的总体时间复杂度为O(n^2 * log(n))

【讨论】:

  • 它将移动所有四个数字。上面的想法是分别考虑每个数字。 “循环”的数字可能有不同的长度,当所有循环相遇时,整个排列就会重复。
  • 添加了解释相同的注释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-14
相关资源
最近更新 更多