📜  前缀反转的最小数量,用于排序前N个数字的排列

📅  最后修改于: 2021-05-05 02:02:09             🧑  作者: Mango

给定N个数字,其中N个数字的排列为前N个。在单个操作中,任何前缀都可以颠倒。任务是找到此类操作的最小数量,以使阵列中的数字按升序排列。

例子:

Input : a[] = {3, 1, 2} 
Output : 2 
Step1: Reverse the complete array a, a[] = {2, 1, 3} 
Step2: Reverse the prefix(0-1) in s, a[] = {1, 2, 3} 

Input : a[] = {1, 2, 4, 3} 
Output : 3 
Step1: Reverse the complete array a, a[] = {3, 4, 2, 1} 
Step2: Reverse the prefix(0-1) in s, a[] = {4, 3, 2, 1} 
Step3: Reverse the complete array a, a[] = {1, 2, 3, 4} 

解决此问题的方法是使用BFS。

  • 将给定数字编码为字符串。对数组进行排序并将其编码为字符串目标
  • 然后从初始排列开始进行BFS。每次检查由反向当前排列的前缀引起的所有排列。
  • 如果未访问,则将其放入队列中,并计算已完成的冲销。
  • 当编码字符串的排列与目标字符串,返回到达此处所需的反转数。
  • 也就是说,完成了字符串的所有排列,并返回了其中的最小值作为答案。

下面是上述方法的实现:

C++
// C++ program to find
// minimum number of prefix reversals
// to sort permutation of first N numbers
#include 
using namespace std;
  
// Function to return the minimum prefix reversals
int minimumPrefixReversals(int a[], int n)
{
    string start = "";
    string destination = "", t, r;
    for (int i = 0; i < n; i++) {
        // converts the number to a character
        // and add  to string
        start += to_string(a[i]);
    }
    sort(a, a + n);
    for (int i = 0; i < n; i++) {
        destination += to_string(a[i]);
    }
  
    // Queue to store the pairs
    // of string and number of reversals
    queue > qu;
    pair p;
  
    // Initially push the original string
    qu.push(make_pair(start, 0));
  
    // if original string is the destination string
    if (start == destination) {
        return 0;
    }
  
    // iterate till queue is empty
    while (!qu.empty()) {
  
        // pair at the top
        p = qu.front();
  
        // string
        t = p.first;
  
        // pop the top-most element
        qu.pop();
  
        // peform prefix reversals for all index and push
        // in the queue and check for the minimal
        for (int j = 2; j <= n; j++) {
            r = t;
  
            // reverse the string till prefix j
            reverse(r.begin(), r.begin() + j);
  
            // if after reversing the string from first i index
            // it is the destination
            if (r == destination) {
                return p.second + 1;
            }
  
            // push the number of reversals for string r
            qu.push(make_pair(r, p.second + 1));
        }
    }
}
  
// Driver Code
int main()
{
  
    int a[] = { 1, 2, 4, 3 };
    int n = sizeof(a) / sizeof(a[0]);
  
    // Calling function
    cout << minimumPrefixReversals(a, n);
  
    return 0;
}
Output:3


Java
// Java program to find minimum 
// number of prefix reversals to
// sort permutation of first N numbers
import java.util.*;
  
public class Main
{
      
    // function to find minimum prefix reversal through BFS
    public static int minimumPrefixReversals(int[] a)
    {
        // size of array 
        int n = a.length;
          
        // string for initial and goal nodes
        String start = "", destination = "";
          
        // string for manipulation in while loop
        String original = "",modified = "";
          
        // node to store temporary values from front of queue
        Node temp = null;
          
        // create the starting string 
        for (int i = 0; i < n; i++)
        start += a[i];
          
        // sort the array and prepare final destination string
        Arrays.sort(a);
        for (int i = 0; i < n; i++)
            destination += a[i];
          
        // this queue will store all the BFS siblings
        Queue q = new LinkedList<>();
          
        // place the starting node in queue
        q.add(new Node(start, 0));
          
        //base case:- if array is already sorted
        if (start == destination)
            return 0;
          
          
        // loop until the size of queue is empty 
        while (q.size() != 0)
        {
            // put front node of queue in temporary variable
            temp = q.poll();
              
            // store the original string at this step
            original = temp.string;
              
            for (int j = 2; j <= n; j++)
            {
                // modified will be used to genrate all 
                // manipulation of original string
                // like if original = 1342
                // modified = 3142 , 4312 , 2431
                  
                modified = original;
                  
                // generate the permutation by reversing 
                modified = reverse (modified , j);
                  
                if (modified.equals(destination))
                {
                    // if string match then return 
                    // the height of the current node
                    return temp.steps + 1;
                }
                  
                // else put this node into queue
                q.add(new Node(modified,temp.steps + 1));
            }
              
        }
          
    // if no case match then default value
    return Integer.MIN_VALUE;
    }
      
    // function to reverse the string upto an index 
    public static String reverse (String s , int index)
    {
        char temp []= s.toCharArray();
        int i = 0;
        while (i < index)
        {
            char c = temp[i];
            temp[i] = temp[index-1];
            temp[index-1] = c;
            i++;index--;
        }
        return String.valueOf(temp);
    }
  
    // Driver code
    public static void main(String []args)
    {
        int a[] = new int []{1,2,4,3};
        System.out.println(minimumPrefixReversals(a));
    }
      
    // Node class to store a combined set of values
    static class Node
    {
        public String string ;
        public int steps;
          
        public Node(String string,int steps)
        {
            this.string = string;
            this.steps= steps;
        }
    }
}
  
// This code is contributed by Sparsh Singhal


C#
// C# program to find minimum 
// number of prefix reversals to
// sort permutation of first N numbers
using System;
using System.Collections.Generic;             
  
class GFG
{
    // Node class to store a combined set of values
    public class Node
    {
        public String str;
        public int steps;
          
        public Node(String str,int steps)
        {
            this.str = str;
            this.steps= steps;
        }
    }
      
    // function to find minimum prefix reversal through BFS
    public static int minimumPrefixReversals(int[] a)
    {
        // size of array 
        int n = a.Length;
          
        // string for initial and goal nodes
        String start = "", destination = "";
          
        // string for manipulation in while loop
        String original = "", modified = "";
          
        // node to store temporary values 
        // from front of queue
        Node temp = null;
          
        // create the starting string 
        for (int i = 0; i < n; i++)
        start += a[i];
          
        // sort the array and prepare 
        // final destination string
        Array.Sort(a);
        for (int i = 0; i < n; i++)
            destination += a[i];
          
        // this queue will store all the BFS siblings
        Queue q = new Queue();
          
        // place the starting node in queue
        q.Enqueue(new Node(start, 0));
          
        //base case:- if array is already sorted
        if (start == destination)
            return 0;
          
          
        // loop until the size of queue is empty 
        while (q.Count != 0)
        {
            // put front node of queue in temporary variable
            temp = q.Dequeue();
              
            // store the original string at this step
            original = temp.str;
              
            for (int j = 2; j <= n; j++)
            {
                // modified will be used to genrate all 
                // manipulation of original string
                // like if original = 1342
                // modified = 3142 , 4312 , 2431
                  
                modified = original;
                  
                // generate the permutation by reversing 
                modified = reverse (modified , j);
                  
                if (modified.Equals(destination))
                {
                    // if string match then return 
                    // the height of the current node
                    return temp.steps + 1;
                }
                  
                // else put this node into queue
                q.Enqueue(new Node(modified, temp.steps + 1));
            }
        }
          
        // if no case match then default value
        return int.MinValue;
    }
      
    // function to reverse the string upto an index 
    public static String reverse (String s, int index)
    {
        char []temp = s.ToCharArray();
        int i = 0;
        while (i < index)
        {
            char c = temp[i];
            temp[i] = temp[index - 1];
            temp[index - 1] = c;
            i++;index--;
        }
        return String.Join("", temp);
    }
  
    // Driver code
    public static void Main(String []args)
    {
        int []a = new int []{1, 2, 4, 3};
        Console.WriteLine(minimumPrefixReversals(a));
    }
}
  
// This code is contributed by 29AjayKumar


输出:
3

时间复杂度: O(N!* N 2 )