📜  求 1 到 N 的排列,使得 A 在左半边最小,B 在右半边最大

📅  最后修改于: 2022-05-13 01:56:09.493000             🧑  作者: Mango

求 1 到 N 的排列,使得 A 在左半边最小,B 在右半边最大

给定三个整数NAB ,任务是找到从1N的成对不同数字的排列,使得A是左半部分的最小元素, B是右半部分的最大元素。还假设N是偶数。如果不存在这样的排列,则打印-1

例子:

朴素方法(蛮力):在这种方法中,生成1N个数字的所有排列,并单独检查每个排列。请按照以下步骤解决此问题:

  • 生成从1N的所有数字排列并将它们存储在一个数组中。
  • 遍历每个排列,如果在下面的排列中A是左半部分的最小值, B是右半部分的最大值,则打印排列。
  • 如果不存在这样的排列,则打印-1

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to generate next permutation
void nextPermutation(vector& nums)
{
    int n = nums.size(), k, l;
    for (k = n - 2; k >= 0; k--) {
        if (nums[k] < nums[k + 1]) {
            break;
        }
    }
    if (k < 0) {
        reverse(nums.begin(), nums.end());
    }
    else {
        for (l = n - 1; l > k; l--) {
            if (nums[l] > nums[k]) {
                break;
            }
        }
        swap(nums[k], nums[l]);
        reverse(nums.begin() + k + 1, nums.end());
    }
}
 
// Factorial function
int factorial(int n)
{
    return (n == 1 || n == 0) ? 1 : factorial(n - 1) * n;
}
 
// Function to returns all the permutations
// of a given array or vector
vector > permute(vector& nums)
{
    vector > permuted;
    int n = nums.size();
    int factn = factorial(n);
    for (int i = 0; i < factn; i++) {
        permuted.push_back(nums);
        nextPermutation(nums);
    }
    return permuted;
}
 
// Function to find the permutation
// of 1 to N numbers
// having A minimas and B maximas
void findPermutation(int n, int a, int b)
{
 
    // Generate the array
    // containing one permutation
    vector nums(n);
    for (int i = 0; i < n; i++) {
        nums[i] = i + 1;
    }
 
    // Generate all the permutations
    vector > allpermutations
        = permute(nums);
 
    int total = allpermutations.size();
    int ansindex = -1;
 
    for (int i = 0; i < total; i++) {
 
        // Find the minima of the left half
        // maxima of the right half
        int leftmin = allpermutations[i][0];
        int rightmax = allpermutations[i][n - 1];
        for (int j = 0; j < n / 2; j++) {
            if (allpermutations[i][j] < leftmin) {
                leftmin = allpermutations[i][j];
            }
        }
 
        for (int j = n / 2; j < n; j++) {
            if (allpermutations[i][j] > rightmax) {
                rightmax = allpermutations[i][j];
            }
        }
        if (leftmin == a && rightmax == b) {
 
            // Store the index
            // of a perfect permutation
            ansindex = i;
            break;
        }
    }
 
    // Print -1 if no such permutation exists
    if (ansindex == -1) {
        cout << -1;
    }
    else {
 
        // Print the perfect permutation if exists
        for (int i = 0; i < n; i++) {
            cout << allpermutations[ansindex][i]
                 << " ";
        }
    }
}
 
// Driver Code
int main()
{
    int N = 6, A = 2, B = 5;
    findPermutation(N, A, B);
    return 0;
}


Python3
# Python code to implement the above approach
 
num =[]
# Function to generate next permutation
def nextPermutation(nums):
    global num
    n = len(nums)
    for k in range(n - 2, -1,-1):
        if (nums[k] < nums[k + 1]):
            break
             
    if (k < 0):
        nums.reverse()
         
    else:
        for l in range(n - 1, k, -1):
            if (nums[l] > nums[k]):
                break
                 
        nums[k], nums[l] = nums[l], nums[k]
        temp = nums[k+1:]
        temp.reverse()
        nums = nums[:k+1] +temp
     
    return nums
 
# Factorial function
def factorial(n):
     
    return 1 if(n == 1 or n == 0) else factorial(n - 1) * n
 
# Function to returns all the permutations
# of a given array or vector
def permute(nums):
    global num
    permuted =[]
    n = len(nums)
    factn = factorial(n)
    for i in range(factn):
        permuted.append(nums)
        nums = nextPermutation(nums)
    permuted.append(nums)
    return permuted
 
# Function to find the permutation
# of 1 to N numbers
# having A minimas and B maximas
def findPermutation(n, a, b):
     
    # Generate the array
    # containing one permutation
    nums = [0]*n
    for i in range(n):
        nums[i] = i + 1
         
    # Generate all the permutations
    allpermutations = permute(nums)
     
    total = len(allpermutations)
    ansindex = -1
      
    for i in range(total):
         
        # Find the minima of the left half
        # maxima of the right half
        leftmin = allpermutations[i][0]
        rightmax = allpermutations[i][n - 1]
        for j in range(n // 2):
            if (allpermutations[i][j] < leftmin):
                leftmin = allpermutations[i][j]
                 
        for j in range(n // 2,n):
            if (allpermutations[i][j] > rightmax):
                rightmax = allpermutations[i][j]
         
        if (leftmin == a and rightmax == b):
             
            # Store the index
            # of a perfect permutation
            ansindex = i
            break
         
    # Pr-1 if no such permutation exists
    if (ansindex == -1):
        print(-1)
         
    else:
         
        # Print the perfect permutation if exists
        for i in range(n):
            print(allpermutations[ansindex][i], end =" ")
 
# Driver Code
N = 6
A = 2
B = 5
findPermutation(N, A, B)
 
# This code is contributed by Shubham Singh


C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to get the desired permutation
void getpermutation(int n, int a, int b)
{
    int left = n - b, right = a - 1;
 
    // When b < n/2 or a > n/2
    if (left > n / 2 || right > n / 2) {
        cout << -1;
    }
 
    // When a and b both are
    // in the same half
    else if (a <= n / 2 && b <= n / 2) {
        cout << -1;
    }
    else if (a > n / 2 && b > n / 2) {
        cout << -1;
    }
 
    // The corner case
    else if (a == n / 2 + 1 && b == n / 2) {
        for (int i = 0; i < n; i++) {
            cout << n - i << " ";
        }
    }
 
    // Rest other combinations
    else {
        for (int i = 0; i < n; i++) {
            if (n - i == b) {
                cout << a << " ";
            }
            else if (n - i == a) {
                cout << b << " ";
            }
            else {
                cout << n - i << " ";
            }
        }
    }
 
    cout << endl;
}
 
// Driver Code
int main()
{
 
    int N = 6, A = 2, B = 5;
    getpermutation(N, A, B);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
 
// Function to get the desired permutation
static void getpermutation(int n, int a, int b)
{
    int left = n - b, right = a - 1;
     
    // When b < n/2 or a > n/2
    if (left > n / 2 || right > n / 2)
    {
        System.out.print(-1);
    }
     
    // When a and b both are
    // in the same half
    else if (a <= n / 2 && b <= n / 2)
    {
        System.out.print(-1);
    }
    else if (a > n / 2 && b > n / 2)
    {
        System.out.print(-1);
    }
     
    // The corner case
    else if (a == n / 2 + 1 && b == n / 2)
    {
        for(int i = 0; i < n; i++)
        {
            System.out.print(n - i + " ");
        }
    }
     
    // Rest other combinations
    else
    {
        for(int i = 0; i < n; i++)
        {
            if (n - i == b)
            {
                System.out.print(a + " ");
            }
            else if (n - i == a)
            {
                System.out.print(b + " ");
            }
            else
            {
                System.out.print(n - i + " ");
            }
        }
    }
    System.out.println();
}
 
// Driver Code
public static void main(String args[])
{
    int N = 6, A = 2, B = 5;
     
    getpermutation(N, A, B);
}
}
 
// This code is contributed by Samim Hossain Mondal.


Python3
# python program for the above approach
 
# Function to get the desired permutation
def getpermutation(n, a, b):
 
    left = n - b
    right = a - 1
 
    # When b < n/2 or a > n/2
    if (left > n / 2 or right > n / 2):
        print(-1)
 
        # When a and b both are
        # in the same half
    elif (a <= n / 2 and b <= n / 2):
        print(-1)
 
    elif (a > n / 2 and b > n / 2):
        print(-1)
 
        # The corner case
    elif (a == n / 2 + 1 and b == n / 2):
        for i in range(0, n):
            print(n - i, end=" ")
 
        # Rest other combinations
    else:
        for i in range(0, n):
            if (n - i == b):
                print(a, end=" ")
 
            elif (n - i == a):
                print(b, end=" ")
 
            else:
                print(n - i, end=" ")
 
    print()
 
# Driver Code
if __name__ == "__main__":
 
    N = 6
    A = 2
    B = 5
 
    getpermutation(N, A, B)
 
    # This code is contributed by rakeshsahni


C#
// C# program for the above approach
using System;
class GFG {
 
  // Function to get the desired permutation
  static void getpermutation(int n, int a, int b)
  {
    int left = n - b, right = a - 1;
 
    // When b < n/2 or a > n/2
    if (left > n / 2 || right > n / 2) {
      Console.Write(-1);
    }
 
    // When a and b both are
    // in the same half
    else if (a <= n / 2 && b <= n / 2) {
      Console.Write(-1);
    }
    else if (a > n / 2 && b > n / 2) {
      Console.Write(-1);
    }
 
    // The corner case
    else if (a == n / 2 + 1 && b == n / 2) {
      for (int i = 0; i < n; i++) {
        Console.Write(n - i + " ");
      }
    }
 
    // Rest other combinations
    else {
      for (int i = 0; i < n; i++) {
        if (n - i == b) {
          Console.Write(a + " ");
        }
        else if (n - i == a) {
          Console.Write(b + " ");
        }
        else {
          Console.Write(n - i + " ");
        }
      }
    }
 
    Console.WriteLine();
  }
 
  // Driver Code
  public static void Main()
  {
 
    int N = 6, A = 2, B = 5;
    getpermutation(N, A, B);
  }
}
 
// This code is contributed by ukasp.


Javascript


输出
2 3 6 1 4 5 

时间复杂度: O(N!)
辅助空间: O(N!)

Efficient Approach (Greedy Method):上述蛮力方法可以使用贪心算法进行优化。贪婪是一种算法范式,它逐步构建解决方案,总是选择下一个提供最明显和直接好处的部分。因此,根据N、A、B的值将问题分解为不同的可用部分。请按照以下步骤解决此问题:

  • 左边的变量初始化为nb ,将右边的变量初始化为a-1。
  • 如果leftright大于n/2则打印-1
  • 否则,如果ab小于等于n/2 ,则打印-1。
  • 否则,如果ab大于n/2 ,则打印-1。
  • 否则,如果a等于n/2+1b等于n/2 ,则将n打印为1作为答案。
  • 否则,使用变量i遍历范围[0, n)并执行以下任务:
    • 如果ni等于ab则打印ab否则打印ni

下面是上述方法的实现:

C++

// C++ program for the above approach
#include 
using namespace std;
 
// Function to get the desired permutation
void getpermutation(int n, int a, int b)
{
    int left = n - b, right = a - 1;
 
    // When b < n/2 or a > n/2
    if (left > n / 2 || right > n / 2) {
        cout << -1;
    }
 
    // When a and b both are
    // in the same half
    else if (a <= n / 2 && b <= n / 2) {
        cout << -1;
    }
    else if (a > n / 2 && b > n / 2) {
        cout << -1;
    }
 
    // The corner case
    else if (a == n / 2 + 1 && b == n / 2) {
        for (int i = 0; i < n; i++) {
            cout << n - i << " ";
        }
    }
 
    // Rest other combinations
    else {
        for (int i = 0; i < n; i++) {
            if (n - i == b) {
                cout << a << " ";
            }
            else if (n - i == a) {
                cout << b << " ";
            }
            else {
                cout << n - i << " ";
            }
        }
    }
 
    cout << endl;
}
 
// Driver Code
int main()
{
 
    int N = 6, A = 2, B = 5;
    getpermutation(N, A, B);
 
    return 0;
}

Java

// Java program for the above approach
import java.util.*;
 
class GFG{
 
// Function to get the desired permutation
static void getpermutation(int n, int a, int b)
{
    int left = n - b, right = a - 1;
     
    // When b < n/2 or a > n/2
    if (left > n / 2 || right > n / 2)
    {
        System.out.print(-1);
    }
     
    // When a and b both are
    // in the same half
    else if (a <= n / 2 && b <= n / 2)
    {
        System.out.print(-1);
    }
    else if (a > n / 2 && b > n / 2)
    {
        System.out.print(-1);
    }
     
    // The corner case
    else if (a == n / 2 + 1 && b == n / 2)
    {
        for(int i = 0; i < n; i++)
        {
            System.out.print(n - i + " ");
        }
    }
     
    // Rest other combinations
    else
    {
        for(int i = 0; i < n; i++)
        {
            if (n - i == b)
            {
                System.out.print(a + " ");
            }
            else if (n - i == a)
            {
                System.out.print(b + " ");
            }
            else
            {
                System.out.print(n - i + " ");
            }
        }
    }
    System.out.println();
}
 
// Driver Code
public static void main(String args[])
{
    int N = 6, A = 2, B = 5;
     
    getpermutation(N, A, B);
}
}
 
// This code is contributed by Samim Hossain Mondal.

Python3

# python program for the above approach
 
# Function to get the desired permutation
def getpermutation(n, a, b):
 
    left = n - b
    right = a - 1
 
    # When b < n/2 or a > n/2
    if (left > n / 2 or right > n / 2):
        print(-1)
 
        # When a and b both are
        # in the same half
    elif (a <= n / 2 and b <= n / 2):
        print(-1)
 
    elif (a > n / 2 and b > n / 2):
        print(-1)
 
        # The corner case
    elif (a == n / 2 + 1 and b == n / 2):
        for i in range(0, n):
            print(n - i, end=" ")
 
        # Rest other combinations
    else:
        for i in range(0, n):
            if (n - i == b):
                print(a, end=" ")
 
            elif (n - i == a):
                print(b, end=" ")
 
            else:
                print(n - i, end=" ")
 
    print()
 
# Driver Code
if __name__ == "__main__":
 
    N = 6
    A = 2
    B = 5
 
    getpermutation(N, A, B)
 
    # This code is contributed by rakeshsahni

C#

// C# program for the above approach
using System;
class GFG {
 
  // Function to get the desired permutation
  static void getpermutation(int n, int a, int b)
  {
    int left = n - b, right = a - 1;
 
    // When b < n/2 or a > n/2
    if (left > n / 2 || right > n / 2) {
      Console.Write(-1);
    }
 
    // When a and b both are
    // in the same half
    else if (a <= n / 2 && b <= n / 2) {
      Console.Write(-1);
    }
    else if (a > n / 2 && b > n / 2) {
      Console.Write(-1);
    }
 
    // The corner case
    else if (a == n / 2 + 1 && b == n / 2) {
      for (int i = 0; i < n; i++) {
        Console.Write(n - i + " ");
      }
    }
 
    // Rest other combinations
    else {
      for (int i = 0; i < n; i++) {
        if (n - i == b) {
          Console.Write(a + " ");
        }
        else if (n - i == a) {
          Console.Write(b + " ");
        }
        else {
          Console.Write(n - i + " ");
        }
      }
    }
 
    Console.WriteLine();
  }
 
  // Driver Code
  public static void Main()
  {
 
    int N = 6, A = 2, B = 5;
    getpermutation(N, A, B);
  }
}
 
// This code is contributed by ukasp.

Javascript


输出
6 2 4 3 5 1 

时间复杂度: O(N)
辅助空间: O(N)