求 1 到 N 的排列,使得 A 在左半边最小,B 在右半边最大
给定三个整数N 、 A和B ,任务是找到从1到N的成对不同数字的排列,使得A是左半部分的最小元素, B是右半部分的最大元素。还假设N是偶数。如果不存在这样的排列,则打印-1 。
例子:
Input: N = 6, A = 2, B = 5
Output: 6, 2, 4, 3, 5, 1
Explanation: A = 2 is the minima of the left half.
B = 5 is the maxima of the right half.
Input: N = 6, A = 1, B = 3
Output: -1
Explanation: No such permutation exists.
朴素方法(蛮力):在这种方法中,生成1到N个数字的所有排列,并单独检查每个排列。请按照以下步骤解决此问题:
- 生成从1到N的所有数字排列并将它们存储在一个数组中。
- 遍历每个排列,如果在下面的排列中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。
- 如果left或right大于n/2则打印-1
- 否则,如果a和b小于等于n/2 ,则打印-1。
- 否则,如果a和b大于n/2 ,则打印-1。
- 否则,如果a等于n/2+1且b等于n/2 ,则将n打印为1作为答案。
- 否则,使用变量i遍历范围[0, n)并执行以下任务:
- 如果ni等于a或b则打印a或b否则打印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)