Open In App

Minimum Operations to Sort Array with Custom Shuffling

Last Updated : 12 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array A[] of length N along with a string S, the task is to output the minimum number of operations required to sort A[]. If it’s not possible then output -1. You can apply the below operation on A[] using S as follows:

  • Choose two distinct indices let’s say i and j such that (i != j) and S[i] != S[j]. Shuffle the elements of subarray A[i, j] as per your choice.
  • Also, shuffle the corresponding characters of S according to those elements.

Examples:

Input: N = 3, A[] = {3, 2, 1}, S = ‘NSN’

Output: 2

Explanation: The operations are performed as:

  • First operation:
    • Choose i = 2 and j = 3 as S[2] = S and S[3] = N, where S[2] != S[3].
    • Then subarray is A[2, 3] = {2, 1}.
      • Now, shuffle A[2, 3] as {1, 2}. Updated A[] is {3, 1, 2}
      • Values in S will also shuffle according to A[2, 3]. S[2, 3] was “SN”, then it will be “NS”. Updated S = “NNS”
  • Second operation:
    • Choose i = 1 and j = 3 as S[1] = N and S[3] = S.
    • Then subarray is A[1, 3] = {3, 2, 1}.
      • Now, shuffled A[1, 3] as {1, 2, 3}. Updated A[] is {1, 2, 3}
      • Values in S will also shuffle according to A[1, 2, 3]. S[1, 3] was “NNS”, then it will be “NSN”. Updated S = “NSN”
  • It can be verified that now A[] is sorted under 2 operations. It can be verified that these are the minimum number of operations. Thus, output is 2.

Input: N = 2, A[] = {2, 1}, S = SS

Output: -1

Explanation: It can be verified that it is not possible to sort A[] using given operation. Therefore, output is -1.

Approach: Implement the idea below to solve the problem

  • First of all, we have to check if A[] is already sorted in increasing order or not, If already sorted then the minimum number of operations required is 0. For checking this, we made a function named as Is_sorted(A[]).
  • Next, We will check, If all the characters in S are either ‘N’ or ‘S’. In such case, we can’t apply any operation because there wouldn’t be two indices such that S[i]!=S[j]. which would result in no change in the order of elements in the A[]. In such cases, it is not possible to sort the A[]. So, the output is -1.
  • If the above two conditions fail, Then find the leftmost and rightmost ‘N’ and ‘S’ characters into the string S.

Checking for two possibilities:

If we can sort A[] by negating some elements between the first ‘N’ and last ‘S’ (inclusive) OR If we can sort A[] by swapping some elements between the first ‘S’ and last ‘N’ (inclusive). If either of these two possibilities is true, then we need only one operation to sort the array. Otherwise, we need 2 operations.

Finally, the minimum number of operations required to sort A[] is printed. It is always possible to sort A[] in at most 2 operations, If sorting is possible using given operation.

Note that the check() function in the program is used to determine if a subarray is already sorted or not by sorting it and comparing it with the original subarray.

Steps were taken to solve the problem:

  • Initial Checks on A[]:
    • Check, if A[] is already sorted or not. If it is, Output 0. Since no operations are needed.
    • Also check if all characters in S are same (all ‘N’ or all ‘S’). If they are, then output -1. Since it’s impossible to sort A[] with the given operations.
  • Find first and last occurrences of N and S:
    • Then find the first and last occurrence of both ‘N’ and ‘S’ in the string in four variables let say firstN, lastN, firstS, and lastS.
  • Check() Function:
    • This function checks two subarrays: A[firstN, lastS] and A[firstS, lastN]. If either of these subarrays can be sorted to make the entire array sorted, it means it’s possible to sort the array with 1 operation.
  • Output:
    • Finally, if either subarray can be sorted to sort the entire array, Then output 1.
    • Otherwise, output 2, indicating that at least two operations are needed to sort the array.

Code to implement the approach:

C++




// CPP code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
 
// Function to check if sorting a subarray from
// 'first' to 'last' makes the entire
// array sorted
bool check(vector<int> arr, int first, int last)
{
    // Sort the subarray from 'first' to 'last'
    sort(arr.begin() + first, arr.begin() + last + 1);
 
    // Check if the entire array is sorted
    if (is_sorted(arr.begin(), arr.end())) {
        return true;
    }
    return false;
}
 
// Function to output the minimum number
// of operations
void min_operations(int N, vector<int> A, string S)
{
    // Create a copy of the array and sort it
    vector<int> A1(N);
    A1 = A;
    sort(A1.begin(), A1.end());
 
    // Check if the A[] is already sorted
    if (is_sorted(A.begin(), A.end())) {
        cout << 0 << "\n";
        return;
    }
 
    // Count the number of 'N'
    int count = 0;
    for (int i = 0; i < N; i++) {
        if (S[i] == 'N') {
            count++;
        }
    }
 
    // If all characters of S are same. Then,
    // it's impossible to sort A[]
    if (count == N || count == 0) {
        cout << "-1"
             << "\n";
        return;
    }
 
    // Find the first and last occurrence of
    // both 'N' and 'S'
    int firstN = -1, firstS = -1, lastN = -1, lastS = -1;
    for (int i = 0; i < N; i++) {
        if (S[i] == 'N') {
            if (firstN == -1) {
                firstN = i;
            }
            lastN = i;
        }
        else {
            if (firstS == -1) {
                firstS = i;
            }
            lastS = i;
        }
    }
 
    // Initialize the minimum number of
    // operations as 2
    int ans = 2;
 
    // If sorting either of two subarrays makes
    // the entire array sorted, update the
    // minimum number of operations to 1
    if (check(A, firstN, lastS)
        || check(A, firstS, lastN)) {
        ans = 1;
    }
 
    // Print the minimum number of operations
    cout << ans << "\n";
}
 
// Drivers code
int main()
{
    // Inputs
    int N = 2;
    vector<int> A = { 2, 1 };
    string S = "NN";
 
    // Function call
    min_operations(N, A, S);
    return 0;
}


Java




import java.util.*;
 
class GFG {
    // Function to check if sorting a subarray from
    // 'first' to 'last' makes the entire array sorted
    static boolean check(Vector<Integer> arr, int first,
                         int last)
    {
        // Sort the subarray from 'first' to 'last'
        Arrays.sort(arr.subList(first, last + 1).toArray());
 
        // Check if the entire array is sorted
        return isSorted(arr);
    }
 
    // Function to check if the vector is sorted
    static boolean isSorted(Vector<Integer> arr)
    {
        Vector<Integer> sortedArr = new Vector<>(arr);
        sortedArr.sort(null);
        return arr.equals(sortedArr);
    }
 
    // Function to output the minimum number of operations
    static void minOperations(int N, Vector<Integer> A,
                              String S)
    {
        // Create a copy of the array and sort it
        Vector<Integer> A1 = new Vector<>(A);
        A1.sort(null);
 
        // Check if the A[] is already sorted
        if (isSorted(A)) {
            System.out.println(0);
            return;
        }
 
        // Count the number of 'N'
        int count = 0;
        for (int i = 0; i < N; i++) {
            if (S.charAt(i) == 'N') {
                count++;
            }
        }
 
        // If all characters of S are the same, it's
        // impossible to sort A[]
        if (count == N || count == 0) {
            System.out.println("-1");
            return;
        }
 
        // Find the first and last occurrence of both 'N'
        // and 'S'
        int firstN = -1, firstS = -1, lastN = -1,
            lastS = -1;
        for (int i = 0; i < N; i++) {
            if (S.charAt(i) == 'N') {
                if (firstN == -1) {
                    firstN = i;
                }
                lastN = i;
            }
            else {
                if (firstS == -1) {
                    firstS = i;
                }
                lastS = i;
            }
        }
 
        // Initialize the minimum number of operations as 2
        int ans = 2;
 
        // If sorting either of two subarrays makes
        // the entire array sorted, update the
        // minimum number of operations to 1
        if (check(A, firstN, lastS)
            || check(A, firstS, lastN)) {
            ans = 1;
        }
 
        // Print the minimum number of operations
        System.out.println(ans);
    }
 
    // Drivers code
    public static void main(String[] args)
    {
        // Inputs
        int N = 2;
        Vector<Integer> A
            = new Vector<>(Arrays.asList(2, 1));
        String S = "NN";
 
        // Function call
        minOperations(N, A, S);
    }
}


Python3




# Function to check if sorting a subarray from
# 'first' to 'last' makes the entire
# array sorted
def check(arr, first, last):
    # Sort the subarray from 'first' to 'last'
    arr[first:last+1] = sorted(arr[first:last+1])
 
    # Check if the entire array is sorted
    return arr == sorted(arr)
 
# Function to output the minimum number
# of operations
def min_operations(N, A, S):
    # Create a copy of the array and sort it
    A1 = sorted(A)
 
    # Check if the A[] is already sorted
    if A == A1:
        print(0)
        return
 
    # Count the number of 'N'
    count = S.count('N')
 
    # If all characters of S are same. Then,
    # it's impossible to sort A[]
    if count == N or count == 0:
        print("-1")
        return
 
    # Find the first and last occurrence of
    # both 'N' and 'S'
    firstN = S.find('N')
    lastN = N - 1 - S[::-1].find('N')
    firstS = S.find('S')
    lastS = N - 1 - S[::-1].find('S')
 
    # Initialize the minimum number of
    # operations as 2
    ans = 2
 
    # If sorting either of two subarrays makes
    # the entire array sorted, update the
    # minimum number of operations to 1
    if check(A, firstN, lastS) or check(A, firstS, lastN):
        ans = 1
 
    # Print the minimum number of operations
    print(ans)
 
# Drivers code
if __name__ == "__main__":
    # Inputs
    N = 2
    A = [2, 1]
    S = "NN"
 
    # Function call
    min_operations(N, A, S)


C#




// C# Implementation
using System;
using System.Collections.Generic;
using System.Linq;
 
class GFG
{
    // Function to check if sorting a subarray from
    // 'first' to 'last' makes the entire array sorted
    static bool Check(List<int> arr, int first, int last)
    {
        // Sort the subarray from 'first' to 'last'
        arr.Sort(first, last - first + 1, null);
 
        // Check if the entire array is sorted
        return IsSorted(arr);
    }
 
    // Function to check if the list is sorted
    static bool IsSorted(List<int> arr)
    {
        List<int> sortedArr = new List<int>(arr);
        sortedArr.Sort();
        return arr.SequenceEqual(sortedArr);
    }
 
    // Function to output the minimum number of operations
    static void MinOperations(int N, List<int> A, string S)
    {
        // Create a copy of the list and sort it
        List<int> A1 = new List<int>(A);
        A1.Sort();
 
        // Check if the A[] is already sorted
        if (IsSorted(A))
        {
            Console.WriteLine(0);
            return;
        }
 
        // Count the number of 'N'
        int count = S.Count(c => c == 'N');
 
        // If all characters of S are the same, it's
        // impossible to sort A[]
        if (count == N || count == 0)
        {
            Console.WriteLine("-1");
            return;
        }
 
        // Find the first and last occurrence of both 'N'
        // and 'S'
        int firstN = -1, firstS = -1, lastN = -1, lastS = -1;
        for (int i = 0; i < N; i++)
        {
            if (S[i] == 'N')
            {
                if (firstN == -1)
                    firstN = i;
                lastN = i;
            }
            else
            {
                if (firstS == -1)
                    firstS = i;
                lastS = i;
            }
        }
 
        // Initialize the minimum number of operations as 2
        int ans = 2;
 
        // If sorting either of two subarrays makes
        // the entire array sorted, update the
        // minimum number of operations to 1
        if (Check(A, firstN, lastS) || Check(A, firstS, lastN))
            ans = 1;
 
        // Print the minimum number of operations
        Console.WriteLine(ans);
    }
 
    // Drivers code
    public static void Main(string[] args)
    {
        // Inputs
        int N = 2;
        List<int> A = new List<int> { 2, 1 };
        string S = "NN";
 
        // Function call
        MinOperations(N, A, S);
    }
}
 
// This code is contributed by Tapesh(tapeshdua420)


Javascript




// Function to check if sorting a subarray from
// 'first' to 'last' makes the entire
// array sorted
function check(arr, first, last) {
    // Sort the subarray from 'first' to 'last'
    arr.splice(first, last - first + 1, ...arr.slice(first, last + 1).sort());
 
    // Check if the entire array is sorted
    return JSON.stringify(arr) === JSON.stringify(arr.slice().sort());
}
 
// Function to output the minimum number
// of operations
function min_operations(N, A, S) {
    // Create a copy of the array and sort it
    const A1 = [...A].sort();
 
    // Check if the A[] is already sorted
    if (JSON.stringify(A) === JSON.stringify(A1)) {
        console.log(0);
        return;
    }
 
    // Count the number of 'N'
    const count = (S.match(/N/g) || []).length;
 
    // If all characters of S are the same, then,
    // it's impossible to sort A[]
    if (count === N || count === 0) {
        console.log("-1");
        return;
    }
 
    // Find the first and last occurrence of
    // both 'N' and 'S'
    const firstN = S.indexOf('N');
    const lastN = N - 1 - [...S].reverse().indexOf('N');
    const firstS = S.indexOf('S');
    const lastS = N - 1 - [...S].reverse().indexOf('S');
 
    // Initialize the minimum number of
    // operations as 2
    let ans = 2;
 
    // If sorting either of two subarrays makes
    // the entire array sorted, update the
    // minimum number of operations to 1
    if (check(A, firstN, lastS) || check(A, firstS, lastN)) {
        ans = 1;
    }
 
    // Print the minimum number of operations
    console.log(ans);
}
 
// Drivers code
// Inputs
const N = 2;
const A = [2, 1];
const S = "NN";
 
// Function call
min_operations(N, A, S);


Output

-1












Time Complexity: O(N)
Auxiliary space: O(N), As extra Vector A1 is used.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads