📜  将排列转换为标识排列所需的最小给定操作数

📅  最后修改于: 2021-06-26 08:50:50             🧑  作者: Mango

给定前n个自然数的排列P (P1,P2,P3,…Pn)。找到将其转换为身份置换的最小数量的操作,即1、2、3,…,n ,其中每个操作定义为:
P [i] = P [P [P [i]]] \forall i从1到n(基于1的索引)。如果没有办法转换,则打印-1

例子:

方法:首先,找到给定排列中的所有循环。在此,循环是一个有向图,其中从元素e到位置e上的元素存在一条边。
例如,这是排列图{4,6,5,3,2,1,1,8,7}

现在,在一个操作中,长度为3k的每个周期分成三个长度为k的周期,而长度为3k + 1或3k + 2的周期不中断。由于最后我们需要长度为1的所有周期,因此,所有周期都必须为3的幂。否则,答案将不存在。答案将是所有循环长度的对数(以3为底)的最大值。

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
  
int calculateCycleOperations(int len)
{
    int cycle_operations = 0;
    while (len) {
        len /= 3;
        ++cycle_operations;
    }
    return --cycle_operations;
}
  
// Function to return the minimum operations required
int minimumOperations(int p[], int n)
{
  
    // Array to keep track of visited elements
    bool visited[n + 1] = { 0 };
  
    // To store the final answer
    int ans = 0;
  
    // Looping through all the elements
    for (int i = 1; i <= n; i++) {
  
        // Current element
        int ele = p[i];
  
        // If current element is not present in the
        // previous cycles then only consider this
        if (!visited[ele]) {
  
            // Mark current element visited so that it
            // will not be considered in other cycles
            visited[ele] = 1;
  
            // To store the length of each cycle
            int len = 1;
            ele = p[ele];
  
            // Calculating cycle length
            while (!visited[ele]) {
                visited[ele] = 1;
                ++len;
                ele = p[ele];
            }
  
            // Operations needed for this cycle to reduce
            // to length 1 (if possible)
            int operations = calculateCycleOperations(len);
  
            // Checking cycle length to be power of 3
            // if not, then return -1
            int num = pow(3, operations);
            if (num != len) {
                return -1;
            }
  
            // Taking maximum of the operations
            ans = max(ans, operations);
        }
    }
    return ans;
}
  
// Driver code
int main()
{
    // 1-based indexing
    int P[] = { -1, 4, 6, 5, 3, 2, 7, 8, 9, 1 };
    int n = (sizeof(P) / sizeof(P[0])) - 1;
  
    // Calling function
    cout << minimumOperations(P, n);
  
    return 0;
}


Java
// Java implementation of the approach
import java.util.*;
  
class GFG
{
  
static int calculateCycleOperations(int len)
{
    int cycle_operations = 0;
    while (len > 0) 
    {
        len /= 3;
        ++cycle_operations;
    }
    return --cycle_operations;
}
  
// Function to return the minimum operations required
static int minimumOperations(int p[], int n)
{
  
    // Array to keep track of visited elements
    int []visited = new int[n+1];
    Arrays.fill(visited,0);
  
    // To store the final answer
    int ans = 0;
  
    // Looping through all the elements
    for (int i = 1; i <= n; i++) 
    {
  
        // Current element
        int ele = p[i];
  
        // If current element is not present in the
        // previous cycles then only consider this
        if (visited[ele] == 0) 
        {
  
            // Mark current element visited so that it
            // will not be considered in other cycles
            visited[ele] = 1;
  
            // To store the length of each cycle
            int len = 1;
            ele = p[ele];
  
            // Calculating cycle length
            while (visited[ele] == 0)
            {
                visited[ele] = 1;
                ++len;
                ele = p[ele];
            }
  
            // Operations needed for this cycle to reduce
            // to length 1 (if possible)
            int operations = calculateCycleOperations(len);
  
            // Checking cycle length to be power of 3
            // if not, then return -1
            int num = (int)Math.pow(3, operations);
            if (num != len) {
                return -1;
            }
  
            // Taking maximum of the operations
            ans = Math.max(ans, operations);
        }
    }
    return ans;
}
  
// Driver code
public static void main(String args[])
{
    // 1-based indexing
    int P[] = { -1, 4, 6, 5, 3, 2, 7, 8, 9, 1 };
    int n = P.length-1;
  
    // Calling function
    System.out.println(minimumOperations(P, n));
}
}
  
// This code is contributed by
// Surendra_Gangwar


Python3
# Python3 implementation of the approach
def calculateCycleOperations(length):
  
    cycle_operations = 0
    while length > 0: 
        length //= 3
        cycle_operations += 1
      
    return cycle_operations - 1
  
# Function to return the minimum 
# operations required
def minimumOperations(p, n):
  
    # Array to keep track of visited elements
    visited = [0] * (n + 1) 
  
    # To store the final answer
    ans = 0
  
    # Looping through all the elements
    for i in range(1, n + 1): 
  
        # Current element
        ele = p[i]
  
        # If current element is not present in the
        # previous cycles then only consider this
        if not visited[ele]: 
  
            # Mark current element visited so that it
            # will not be considered in other cycles
            visited[ele] = 1
  
            # To store the length of each cycle
            length = 1
            ele = p[ele]
  
            # Calculating cycle length
            while not visited[ele]: 
                visited[ele] = 1
                length += 1
                ele = p[ele]
              
            # Operations needed for this cycle to
            # reduce to length 1 (if possible)
            operations = calculateCycleOperations(length)
  
            # Checking cycle length to be power
            # of 3 if not, then return -1
            num = pow(3, operations)
            if num != length: 
                return -1
  
            # Taking maximum of the operations
            ans = max(ans, operations)
          
    return ans
  
# Driver code
if __name__ == "__main__":
  
    # 1-based indexing
    P = [-1, 4, 6, 5, 3, 2, 7, 8, 9, 1] 
    n = len(P) - 1
  
    # Calling function
    print(minimumOperations(P, n))
  
# This code is contributed by Rituraj Jain


C#
// C# implementation of the above approach 
using System;
  
class GFG 
{ 
  
    static int calculateCycleOperations(int len) 
    { 
        int cycle_operations = 0; 
        while (len > 0) 
        { 
            len /= 3; 
            ++cycle_operations; 
        } 
        return --cycle_operations; 
    } 
      
    // Function to return the minimum operations required 
    static int minimumOperations(int []p, int n) 
    { 
      
        // Array to keep track of visited elements 
        int []visited = new int[n+1]; 
  
        // To store the final answer 
        int ans = 0; 
      
        // Looping through all the elements 
        for (int i = 1; i <= n; i++) 
        { 
      
            // Current element 
            int ele = p[i]; 
      
            // If current element is not present in the 
            // previous cycles then only consider this 
            if (visited[ele] == 0) 
            { 
      
                // Mark current element visited so that it 
                // will not be considered in other cycles 
                visited[ele] = 1; 
      
                // To store the length of each cycle 
                int len = 1; 
                ele = p[ele]; 
      
                // Calculating cycle length 
                while (visited[ele] == 0) 
                { 
                    visited[ele] = 1; 
                    ++len; 
                    ele = p[ele]; 
                } 
      
                // Operations needed for this cycle to reduce 
                // to length 1 (if possible) 
                int operations = calculateCycleOperations(len); 
      
                // Checking cycle length to be power of 3 
                // if not, then return -1 
                int num = (int)Math.Pow(3, operations); 
                if (num != len) 
                { 
                    return -1; 
                } 
      
                // Taking maximum of the operations 
                ans = Math.Max(ans, operations); 
            } 
        } 
        return ans; 
    } 
      
    // Driver code 
    public static void Main() 
    { 
        // 1-based indexing 
        int []P = { -1, 4, 6, 5, 3, 2, 7, 8, 9, 1 }; 
        int n = P.Length-1; 
      
        // Calling function 
        Console.WriteLine(minimumOperations(P, n)); 
    } 
} 
  
// This code is contributed by Ryuga


PHP


输出:
2

时间复杂度:O(N * LogN)

如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。