【问题标题】:Minimum number of iterations最小迭代次数
【发布时间】:2021-01-16 10:38:38
【问题描述】:

给定一个数组,其数字范围从 1 到 n(不重复),其中 n = 数组的大小。 我们可以进行以下操作:
arr[i] = arr[arr[i]-1] , 0

现在,当我们对整个数组执行上述操作时,会考虑一次迭代。 我们的任务是在遇到之前遇到的序列后找到迭代次数。

Constraints :  
a) Array has no duplicates
b) 1 <= arr[i] <= n , 0 <= i < n  
c) 1 <= n <= 10^6  

例 1:

n = 5  
arr[] = {5, 4, 2, 1, 3}  

  
After 1st iteration array becomes : {3, 1, 4, 5, 2}  
After 2nd iteration array becomes : {4, 3, 5, 2, 1}  
After 3rd iteration array becomes : {2, 5, 1, 3, 4}  
After 4th iteration array becomes : {5, 4, 2, 1, 3}    
In the 4th iteration, the sequence obtained is already seen before  
So the expected output is 4.

这个问题是在一项招聘测试中被问到的,所以我没有任何指向该问题的链接。 给出了 2 个示例测试用例,我记得上面给出了一个。我非常感谢您对这个问题的任何帮助

附言
我能够编写蛮力解决方案,其中我将所有结果存储在一个 Set 中,然后继续前进到下一个排列。但它给了TLE

【问题讨论】:

  • 你的问题是什么?您需要什么帮助?
  • 是的,正如@StPiere 所说,我需要提示或算法。我无法想到任何最佳解决方案。我只能用蛮力编码,但它给了 TLE
  • @crazyCoder 你是如何将结果存储在一个集合中的?作为字符串?也许 Trie 数据结构更适合存储已经遇到的排列

标签: c++ arrays algorithm


【解决方案1】:

首先,请注意,长度为 n 的数组包含 1、2、...、n 且没有重复项是 permutation

接下来,观察arr[i] := arr[arr[i] - 1]平方排列。 也就是说,将排列视为symmetric group S_n 的元素,其中乘法是排列的组合。 那么上面的操作就是arr := arr * arr

所以,就排列及其组成而言,问题如下:

给定一个排列 p (= arr)。
考虑排列 p, p^2, p^4, p^8, p^16, ...
它们之间有多少不同的元素?


现在,要解决它,请考虑排列的cycle notation。 每个排列都是不相交循环的产物。 例如,6 1 4 3 5 2 是以下循环的乘积:(1 6 2) (3 4) (5)。 换句话说,这个排列的每一个应用:

  • 沿循环移动位置 1、6、2 的元素;
  • 沿循环移动位置 4、3 的元素;
  • 保留位置 5 的元素。

所以,当我们考虑 p^k(取一个恒等排列并将排列 p 应用于它 k 次)时,我们实际上处理了三个独立的动作:

  • 沿循环移动位置 1、6、2 的元素 k 次;
  • 沿循环移动位置 4、3 的元素 k 次;
  • 将位置 5 的元素保留 k 次。

现在,考虑到,在 d 次应用一个长度为 d 的循环之后,它只是将所有相应的元素返回到它们的初始位置。 因此,我们实际上可以将 p^k 表示为:

  • 沿循环移动位置 1、6、2 的元素,(k mod 3) 次;
  • 沿循环移动位置 4、3 的元素,(k mod 2) 次;
  • 保留位置 5 的元素。

我们现在可以证明(使用Chinese Remainder Theorem,或仅使用群论的一般知识)排列 p,p^2,p^3,p^4,p^5,... 都是不同的到 p^m,其中 m 是所有循环长度的least common multiple。 在 p = 6 1 4 3 5 2 的示例中,我们有 p、p^2、p^3、p^4、p^5 和 p^6 都是不同的。 但是 p^6 是恒等排列:沿着长度为 2 或 3 的循环移动六次会导致项目位于其初始位置。 所以 p^7 与 p^1 相同,p^8 与 p^2 相同,以此类推。


然而我们的问题更难:我们想知道不同排列的数量不是在 p, p^2, p^3, p^4, p^5, ... 之间,而是在 p, p^2, p^4, p^8, p^16, ...:p 的 2 次方。 为此,请考虑我们排列中的所有循环长度 c_1、c_2、...、c_r。 对于每个c_i,求2^k mod c_i的前周期和周期:

  • 例如,c_1 = 3,并且 2^k mod 3 看起来像 1, 2, 1, 2, 1, 2, ...,即 (1, 2) 具有前周期 0 和周期 2。

  • 作为另一个例子,c_2 = 2,并且 2^k mod 2 看起来像 1, 0, 0, 0, ...,即 1, (0) 与前周期 1 和周期 1。

在这个问题中,这部分可以简单地完成,只需在某个数组中标记访问过的数字 mod c_i。

再次由中国剩余定理,在考虑了所有前周期之后,整个周期系统的周期将是所有单个周期的最小公倍数。

剩下的就是考虑前期。 无论如何,这些都可以使用您的幼稚解决方案进行处理,因为这里的前期长度最多为 log_2 n。 答案是所有单个周期的最小公倍数,如上计算,加上最长的前期长度。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-04
    • 1970-01-01
    • 1970-01-01
    • 2019-03-13
    相关资源
    最近更新 更多