Open In App

Count operations to sort given Permutation Array in increasing order

Last Updated : 07 Dec, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an unsorted permutation array of size N and an integer K ( 1 ≤ K ≤ N ), the task is to sort this permutation array in increasing order in the minimum number of steps, where in each step K elements have to be removed from the array and inserted at the front in increasing order and remaining elements should be in arbitrary order.

Examples:

Input: N = 5, P[] = [ 2, 4, 1, 5, 3 ], K = 2
Output: 2
Explanation: Following are the operations that can be performed to sort the permutation in increasing order.

  • Operation1: Choose elements 3, 4 remove them from P then sort them in increasing order – 4, 3 and finally add them in front of P, So, P becomes [3, 4, 2, 1, 5].
  • Operation 2: Choose elements 1, 2 remove them from P then sort them in increasing order – 1, 2 and finally add them in front of P, So P becomes [1, 2, 3, 4, 5}.

So the minimum number of operations required to sort the permutation P in increasing order is 2.

Input : N = 3, P[] = [3, 1, 2],  K = 1
Output:
Explanation: Following are the operations that can be performed to sort the permutation in increasing order.

  • Operation 1: Choose element 2 remove it from P then sort it in increasing order – 2 and finally add it in front of P, So P becomes [2, 3, 1].
  • Operation 2: Choose element 3 remove it from P then sort it in increasing order – 1 and finally add it in front of P, So P becomes [ 1, 2, 3 ].

So the minimum number of operations required to sort the permutation P in increasing order is 2.

Approach: This can be solved by the following idea:

Suppose x elements do not participate in any operation means they are already sorted in increasing order. And since this x must be maximized to minimize the number of operations, we need to find the maximal subsequence of the numbers […2, 1]. Let this sequence have w numbers, then the answer is ceil((n − w) / k).

Follow the steps to solve the problem:

  • Initialize correct_pos with 0.
  • Initialize counter with 0.
  • Run a loop from i: N-1 to 0 and check:
    • If ( P[i] == counter ) then increment correct_pos with 1 and counter with 1.
  • Calculate the Number of wrong_pos elements by ( N – correct_pos ).
  • Calculate minimum number operation by taking ceil of ( wrong_pos / K ).
  • Return the minimum number of operations. 

Below is the implementation of the above approach:

C++




// C++ code for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function performing calculation
int min_operation_to_sort(int N, vector<int>& P, int K)
{
 
    // Initializing correct_pos
    // varaible with 0
    int correct_pos = 0;
 
    // Initializing counter with 1
    int counter = 1;
 
    for (int i = N - 1; i >= 0; i--) {
 
        // If counter is equal to P[i] then
        // correct_pos is incremented with 1.
        if (P[i] == counter) {
 
            correct_pos++;
 
            // Counter is incremented
            counter++;
        }
    }
 
    // Number of wrong_pos is calculated
    int wrong_pos = N - correct_pos;
 
    // Number of operation calculated
    int min_operation = (wrong_pos + K - 1) / K;
 
    // Returning minimum number
    // of operations
    return min_operation;
}
 
// Driver Code
int main()
{
 
    int N = 5;
    vector<int> P = { 2, 4, 1, 5, 3 };
 
    // Number of elements to be choosen
    int K = 2;
 
    // Calling function performing operation
    // and printing the result.
    cout << min_operation_to_sort(N, P, K);
    return 0;
}


Java




import java.util.*;
 
public class Main {
    // Function performing calculation
    public static int minOperationToSort(int N, List<Integer> P, int K) {
 
        // Initializing correct_pos variable with 0
        int correct_pos = 0;
 
        // Initializing counter with 1
        int counter = 1;
 
        for (int i = N - 1; i >= 0; i--) {
 
            // If counter is equal to P[i] then
            // correct_pos is incremented with 1.
            if (P.get(i) == counter) {
 
                correct_pos++;
 
                // Counter is incremented
                counter++;
            }
        }
 
        // Number of wrong_pos is calculated
        int wrong_pos = N - correct_pos;
 
        // Number of operation calculated
        int min_operation = (wrong_pos + K - 1) / K;
 
        // Returning minimum number of operations
        return min_operation;
    }
 
    // Driver Code
    public static void main(String[] args) {
 
        int N = 5;
        List<Integer> P = new ArrayList<>(Arrays.asList(2, 4, 1, 5, 3));
 
        // Number of elements to be chosen
        int K = 2;
 
        // Calling function performing operation
        // and printing the result.
        System.out.println(minOperationToSort(N, P, K));
    }
}
 
//This code is contributed by Akash Jha


Python3




# Python3 code for the above approach
 
# Function performing calculation
def min_operation_to_sort(N, P, K):
    # Initializing correct_pos
    # variable with 0
    correct_pos = 0
 
    # Initializing counter with 1
    counter = 1
 
    for i in range(N - 1, -1, -1):
        # If counter is equal to P[i] then
        # correct_pos is incremented with 1.
        if P[i] == counter:
            correct_pos += 1
            # Counter is incremented
            counter += 1
 
    # Number of wrong_pos is calculated
    wrong_pos = N - correct_pos
 
    # Number of operation calculated
    min_operation = (wrong_pos + K - 1) // K
 
    # Returning minimum number
    # of operations
    return min_operation
 
 
# Driver Code
N = 5
P = [2, 4, 1, 5, 3]
 
# Number of elements to be chosen
K = 2
 
# Calling function performing operation
# and printing the result.
print(min_operation_to_sort(N, P, K))
 
# This code is contributed by Prajwal Kandekar


C#




using System;
using System.Collections.Generic;
 
class Program {
    // Function performing calculation
    static int min_operation_to_sort(int N, List<int> P, int K) {
 
        // Initializing correct_pos variable with 0
        int correct_pos = 0;
 
        // Initializing counter with 1
        int counter = 1;
 
        for (int i = N - 1; i >= 0; i--) {
 
            // If counter is equal to P[i] then
            // correct_pos is incremented with 1.
            if (P[i] == counter) {
 
                correct_pos++;
 
                // Counter is incremented
                counter++;
            }
        }
 
        // Number of wrong_pos is calculated
        int wrong_pos = N - correct_pos;
 
        // Number of operation calculated
        int min_operation = (wrong_pos + K - 1) / K;
 
        // Returning minimum number of operations
        return min_operation;
    }
 
    // Driver Code
    static void Main(string[] args) {
 
        int N = 5;
        List<int> P = new List<int>() { 2, 4, 1, 5, 3 };
 
        // Number of elements to be chosen
        int K = 2;
 
        // Calling function performing operation
        // and printing the result.
        Console.WriteLine(min_operation_to_sort(N, P, K));
    }
}
 
// This code is contributed by Akash Jha


Javascript




function min_operation_to_sort(N, P, K) {
 
    // Initializing correct_pos variable with 0
    let correct_pos = 0;
 
    // Initializing counter with 1
    let counter = 1;
 
    for (let i = N - 1; i >= 0; i--) {
 
        // If counter is equal to P[i] then
        // correct_pos is incremented with 1.
        if (P[i] == counter) {
 
            correct_pos++;
 
            // Counter is incremented
            counter++;
        }
    }
 
    // Number of wrong_pos is calculated
    let wrong_pos = N - correct_pos;
 
    // Number of operation calculated
    let min_operation = Math.ceil(wrong_pos / K);
 
    // Returning minimum number of operations
    return min_operation;
}
 
// Driver Code
let N = 5;
let P = [2, 4, 1, 5, 3];
 
// Number of elements to be chosen
let K = 2;
 
// Calling function performing operation
// and printing the result.
console.log(min_operation_to_sort(N, P, K));
 
// This code is contributed by Akash Jha


Output

2

Time Complexity:  O(N)
Auxiliary Space: O(1)

Another Approach:

By using the cycle: A cycle in a permutation is a sequence of elements that can be cyclically permuted, which means that the elements can be shifted to the right or left within the sequence without changing the order of the elements. For example, the permutation [3, 1, 4, 2] has two cycles: [3, 4, 2, 1] and [1].

This can sort the permutation by performing a series of cyclic permutations, where each cyclic permutation involves only elements that belong to the same cycle. In each cycle,  sort the elements by performing a series of swaps. The number of swaps required to sort a cycle is equal to the length of the cycle minus one.

Follow the steps to solve the problem:

  1. Initialize a list of visited elements to all False.
  2. Initialize a variable for the number of operations to zero.
  3. For each element in the permutation, if the element has not been visited, then:
    a. Start a new cycle with this element.
    b. While the cycle has not returned to the starting element:
    i. Mark the current element as visited.
    ii. Move to the next element in the cycle.
    iii. If the next element has not been visited, add it to the cycle.
    c. Sort the cycle by performing a series of swaps, and increment the number of operations by the number of swaps.
  4. Return the number of operations.
     

Below is the implementation of the above approach:

C++




#include <cmath>
#include <iostream>
#include <vector>
 
using namespace std;
 
int find_min_operations(int N, vector<int>& P, int K)
{
    vector<bool> visited(N, false);
    int num_ops = 0;
    for (int i = 0; i < N; i++) {
        if (!visited[i]) {
            int cycle_start = i;
            int cycle_length = 0;
            while (!visited[cycle_start]) {
                visited[cycle_start] = true;
                cycle_start = P[cycle_start] - 1;
                cycle_length++;
            }
            num_ops += ceil((double)(cycle_length - 1) / K);
        }
    }
    return num_ops;
}
 
int main()
{
    int N = 5, K = 2;
    vector<int> P = { 2, 4, 1, 5, 3 };
    int min_ops = find_min_operations(N, P, K);
    cout << "Minimum number of operations: " << min_ops
         << endl;
    return 0;
}


Java




import java.util.*;
 
public class Main {
    public static int
    findMinOperations(int N, List<Integer> P, int K)
    {
        // Keep track of visited indices
        boolean[] visited = new boolean[N];
        int numOps = 0;
        for (int i = 0; i < N; i++) {
            if (!visited[i]) {
                // Found a cycle starting from i
                int cycleStart = i;
                int cycleLength = 0;
                while (!visited[cycleStart]) {
                    // Mark the current index as visited and
                    // move to the next index in the cycle
                    visited[cycleStart] = true;
                    cycleStart = P.get(cycleStart) - 1;
                    cycleLength++;
                }
                // Calculate the number of operations needed
                // to sort this cycle
                numOps += Math.ceil(
                    (double)(cycleLength - 1) / K);
            }
        }
        return numOps;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int N = 5, K = 2;
        List<Integer> P = Arrays.asList(2, 4, 1, 5, 3);
        int minOps = findMinOperations(N, P, K);
        System.out.println("Minimum number of operations: "
                           + minOps);
    }
}


Python3




import math
 
# function to find the minimum number of operations required
def find_min_operations(N, P, K):
    # list to visited elements
    visited = [False] * N
  
    num_ops = 0
     
    for i in range(N):
        # if the element is not visited, it is the start of a new cycle
        if not visited[i]:
            cycle_start = i
            cycle_length = 0
            # keep following the permutation until we reach the start of the cycle
            while not visited[cycle_start]:
                visited[cycle_start] = True
                cycle_start = P[cycle_start] - 1
                cycle_length += 1
            # calculate the number of operations required for this cycle and add it to the total
            num_ops += math.ceil((cycle_length - 1) / K)
    # return the answer
    return num_ops
 
# example inputs
N = 5
K = 2
P = [2, 4, 1, 5, 3]
 
# call the function and print the result
min_ops = find_min_operations(N, P, K)
print("Minimum number of operations:", min_ops)


C#




using System;
 
class Program
{
    static void Main()
    {
        // Example inputs
        int N = 5;
        int K = 2;
        int[] P = { 2, 4, 1, 5, 3 };
 
        // Call the function and print the result
        int minOps = FindMinOperations(N, P, K);
        Console.WriteLine("Minimum number of operations: " + minOps);
    }
 
    // Function to find the minimum number of operations required
    static int FindMinOperations(int N, int[] P, int K)
    {
        // Array to store visited elements
        bool[] visited = new bool[N];
 
        int numOps = 0;
 
        for (int i = 0; i < N; i++)
        {
            // If the element is not visited, it is the start of a new cycle
            if (!visited[i])
            {
                int cycleStart = i;
                int cycleLength = 0;
 
                // Keep following the permutation until we reach the start of the cycle
                while (!visited[cycleStart])
                {
                    visited[cycleStart] = true;
                    cycleStart = P[cycleStart] - 1;
                    cycleLength += 1;
                }
 
                // Calculate the number of operations required for this cycle and add it to the total
                numOps += (int)Math.Ceiling((cycleLength - 1) / (double)K);
            }
        }
 
        // Return the answer
        return numOps;
    }
}


Javascript




function find_min_operations(N, P, K) {
    // list to visited elements
    var visited = new Array(N).fill(false);
     
    var num_ops = 0;
     
    for (var i = 0; i < N; i++) {
        // if the element is not visited, it is the start of a new cycle
        if (!visited[i]) {
            cycle_start = i;
            cycle_length = 0;
            // keep following the permutation until we reach
            // the start of the cycle
            while (!visited[cycle_start]) {
         
                visited[cycle_start] = true;
                cycle_start = P[cycle_start] - 1;
                cycle_length++;
            }
            // calculate the number of operations required for
            // this cycle and add it to the total
            num_ops += Math.ceil((cycle_length - 1) / K);
        }
    }
    // return the answer
    return num_ops;
}
 
// example inputs
var N = 5;
var K = 2;
var P = [2, 4, 1, 5, 3];
 
// call the function and print the result
 
var min_ops = find_min_operations(N, P, K);
console.log("Minimum number of operations:", min_ops);
 
// This code is contribtued by Tapesh(tapeshdua420)


Output

Minimum number of operations: 2

Time Complexity:  O(N)
Auxiliary Space: O(N)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads