查找具有 X 局部最大值(峰)和 Y 局部最小值(谷)的数字 1 到 N 的排列
给定三个整数N 、 A和B ,任务是找到从1到N的成对不同数字的排列,该排列恰好具有“A”局部最小值和“B”局部最大值。
- 局部最小值被定义为小于其相邻元素的元素。
- 局部最大值定义为大于其相邻元素的元素。
- 整个排列的第一个和最后一个元素永远不能是局部最小值或最大值。
如果不存在这样的排列,则打印-1 。
例子 :
Input: N = 6 , A = 2 , B = 2
Output: 1, 3, 2, 5, 4, 6
Explanation :
2 local minima’s: 2 and 5
2 local maxima’s: 3 and 5
Input: N = 5 , A = 2 , B = 2
Output: -1
朴素方法(蛮力):在这种方法中,生成 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++) {
// Count local minima and local maximas for each
// permutation
int minc = 0, maxc = 0;
for (int j = 1; j < n - 1; j++) {
if (allpermutations[i][j]
> allpermutations[i][j - 1]
&& allpermutations[i][j]
> allpermutations[i][j + 1]) {
maxc++;
}
if (allpermutations[i][j]
< allpermutations[i][j - 1]
&& allpermutations[i][j]
< allpermutations[i][j + 1]) {
minc++;
}
}
if (minc == a && maxc == 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] << " ";
}
}
}
int main()
{
int N = 6, A = 2, B = 2;
findPermutation(N, A, B);
return 0;
}
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the permutation of 1 to N numbers
// having A minimas and B maximas
void findPermutation(int N, int A, int B)
{
// Create the result array
vector arr(N);
for (int i = 0; i < N; i++) {
arr[i] = -1;
}
// If the absolute difference between A and B is
// greater 1 or A+B is greater than N-2, then return -1
if (abs(A - B) > 1 || A + B > N - 2) {
cout << -1;
}
else {
if (A > B) {
// Initialize maxValue with N
int maxValue = N;
// Create a maxima's
for (int i = 1; i < N - 1 && A > 0; i += 2) {
arr[i] = maxValue;
maxValue--;
A--;
}
// Fill other elements in decreasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = maxValue;
maxValue--;
}
}
}
else if (A < B) {
// Initialize minValue with 1
int minValue = 1;
// Create B minima's
for (int i = 1; i < N - 1 && B > 0; i += 2) {
arr[i] = minValue;
minValue++;
B--;
}
// Fill other elements in increasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = minValue;
minValue++;
}
}
}
else if (A == B) {
// Initialize maxValue with n and minValue with
// 1
int minValue = 1, maxValue = N;
arr[0] = minValue;
minValue++;
// Initialize fill equal number of minima and
// maximas
for (int i = 1; i < N - 1 && A > 0; i += 2) {
arr[i] = maxValue;
arr[i + 1] = minValue;
A--;
maxValue--;
minValue++;
}
// Fill the rest in increasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = minValue;
minValue++;
}
}
}
// Print the output
for (int i = 0; i < N; i++) {
cout << arr[i] << " ";
}
}
cout << endl;
}
// Driver Code
int main()
{
int N = 6, A = 2, B = 1;
findPermutation(N, A, B);
return 0;
}
Java
// Java program for the above approach
class GFG{
// Function to find the permutation of 1 to N numbers
// having A minimas and B maximas
static void findPermutation(int N, int A, int B)
{
// Create the result array
int []arr = new int[N];
for (int i = 0; i < N; i++) {
arr[i] = -1;
}
// If the absolute difference between A and B is
// greater 1 or A+B is greater than N-2, then return -1
if (Math.abs(A - B) > 1 || A + B > N - 2) {
System.out.print(-1);
}
else {
if (A > B) {
// Initialize maxValue with N
int maxValue = N;
// Create a maxima's
for (int i = 1; i < N - 1 && A > 0; i += 2) {
arr[i] = maxValue;
maxValue--;
A--;
}
// Fill other elements in decreasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = maxValue;
maxValue--;
}
}
}
else if (A < B) {
// Initialize minValue with 1
int minValue = 1;
// Create B minima's
for (int i = 1; i < N - 1 && B > 0; i += 2) {
arr[i] = minValue;
minValue++;
B--;
}
// Fill other elements in increasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = minValue;
minValue++;
}
}
}
else if (A == B) {
// Initialize maxValue with n and minValue with
// 1
int minValue = 1, maxValue = N;
arr[0] = minValue;
minValue++;
// Initialize fill equal number of minima and
// maximas
for (int i = 1; i < N - 1 && A > 0; i += 2) {
arr[i] = maxValue;
arr[i + 1] = minValue;
A--;
maxValue--;
minValue++;
}
// Fill the rest in increasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = minValue;
minValue++;
}
}
}
// Print the output
for (int i = 0; i < N; i++) {
System.out.print(arr[i]+ " ");
}
}
System.out.println();
}
// Driver Code
public static void main(String[] args)
{
int N = 6, A = 2, B = 1;
findPermutation(N, A, B);
}
}
// This code is contributed by 29AjayKumar
Python3
# Python 3 program for the above approach
# Function to find the permutation of 1 to N numbers
# having A minimas and B maximas
def findPermutation(N, A, B):
# Create the result array
arr = [0]*(N)
for i in range(N):
arr[i] = -1
# If the absolute difference between A and B is
# greater 1 or A+B is greater than N-2, then return -1
if (abs(A - B) > 1 or A + B > N - 2):
print(-1)
else:
if (A > B):
# Initialize maxValue with N
maxValue = N
# Create a maxima's
i = 1
while i < N - 1 and A > 0:
arr[i] = maxValue
maxValue -= 1
A -= 1
i += 2
# Fill other elements in decreasing order
for i in range(N):
if (arr[i] == -1):
arr[i] = maxValue
maxValue -= 1
elif (A < B):
# Initialize minValue with 1
minValue = 1
# Create B minima's
i = 1
while i < N - 1 and B > 0:
arr[i] = minValue
minValue += 1
B -= 1
i += 2
# Fill other elements in increasing order
for i in range(N):
if (arr[i] == -1):
arr[i] = minValue
minValue += 1
elif (A == B):
# Initialize maxValue with n and minValue with
# 1
minValue = 1
maxValue = N
arr[0] = minValue
minValue += 1
# Initialize fill equal number of minima and
# maximas
i = 1
while i < N - 1 and A > 0:
arr[i] = maxValue
arr[i + 1] = minValue
A -= 1
maxValue -= 1
minValue += 1
i += 2
# Fill the rest in increasing order
for i in range(N):
if (arr[i] == -1):
arr[i] = minValue
minValue += 1
# Print the output
for i in range(N):
print(arr[i], end=" ")
print()
# Driver Code
if __name__ == "__main__":
N = 6
A = 2
B = 1
findPermutation(N, A, B)
# This code is contributed by ukasp.
C#
// C# program for the above approach
using System;
class GFG{
// Function to find the permutation of 1 to N numbers
// having A minimas and B maximas
static void findPermutation(int N, int A, int B)
{
// Create the result array
int []arr = new int[N];
for (int i = 0; i < N; i++) {
arr[i] = -1;
}
// If the absolute difference between A and B is
// greater 1 or A+B is greater than N-2, then return -1
if (Math.Abs(A - B) > 1 || A + B > N - 2) {
Console.Write(-1);
}
else {
if (A > B) {
// Initialize maxValue with N
int maxValue = N;
// Create a maxima's
for (int i = 1; i < N - 1 && A > 0; i += 2) {
arr[i] = maxValue;
maxValue--;
A--;
}
// Fill other elements in decreasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = maxValue;
maxValue--;
}
}
}
else if (A < B) {
// Initialize minValue with 1
int minValue = 1;
// Create B minima's
for (int i = 1; i < N - 1 && B > 0; i += 2) {
arr[i] = minValue;
minValue++;
B--;
}
// Fill other elements in increasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = minValue;
minValue++;
}
}
}
else if (A == B) {
// Initialize maxValue with n and minValue with
// 1
int minValue = 1, maxValue = N;
arr[0] = minValue;
minValue++;
// Initialize fill equal number of minima and
// maximas
for (int i = 1; i < N - 1 && A > 0; i += 2) {
arr[i] = maxValue;
arr[i + 1] = minValue;
A--;
maxValue--;
minValue++;
}
// Fill the rest in increasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = minValue;
minValue++;
}
}
}
// Print the output
for (int i = 0; i < N; i++) {
Console.Write(arr[i]+ " ");
}
}
Console.Write("\n");
}
// Driver Code
public static void Main()
{
int N = 6, A = 2, B = 1;
findPermutation(N, A, B);
}
}
// This code is contributed by Samim Hossain Mondal.
Javascript
输出
1 3 2 5 4 6
时间复杂度: O(N!)
辅助空间: O(N!)
有效方法(贪婪方法):
上述蛮力方法可以使用贪心算法进行优化。贪婪是一种算法范式,它逐步构建解决方案,总是选择下一个提供最明显和直接好处的部分。因此,根据N 、 A 、 B的值将问题分解为不同的可用部分。请按照以下步骤解决此问题:
- 由于整个排列的第一个和最后一个元素不能是最大值或最小值,因此最大值和最小值的总数必须小于或等于N-2 。所以如果(A + B > N -2) ,打印-1 。
- 此外,不能有两个连续的最小值或最大值。两个连续的最大值之间必须有一个最小值,两个连续的最小值之间必须有一个最大值。因此,最小值和最大值的总数之间的绝对差必须小于或等于 1。因此,如果A和B之间的绝对差超过1 ,则打印-1 。我们可以很容易地从下图中看到这一点。
- 完成两个极端情况后,创建两个变量, minValue用于存储排列的最小值, maxValue用于存储 maxValue。现在将问题分为三种不同的情况,即(A > B) 、 (A < B)和(A=B) 。现在分别解决每种情况:
- If (A > B):将minValue初始化为 1,并用从索引 2 开始的minValue填充数组A次。每次插入后,将minValue增加 1,因为值应该是不同的。填充时,请确保在每次插入后将一个索引留空,因为两个最小值不可能连续驻留。创建最小值后,按递增顺序填充数组的其余部分,这样就不会创建新的最小值。
- If (B > A):将maxValue初始化为N ,并从索引2开始用maxValue填充数组B次。每次插入后,将maxValue减少 1,因为这些值应该是不同的。填充时,请确保在每次插入后将一个索引留空,因为两个最大值不可能连续驻留。创建B最大值后,按降序填充数组的其余部分,这样就不会创建新的最大值。
- If (A = B):然后初始化两个值minValue为 1 和maxValue为N 。用minValue填充数组的第一个元素并将minValue增加 1。然后用maxValue填充偶数索引并将maxValue减少 1 并用minValue填充奇数索引并将minValue增加1次。现在,按递增顺序填补其余职位。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the permutation of 1 to N numbers
// having A minimas and B maximas
void findPermutation(int N, int A, int B)
{
// Create the result array
vector arr(N);
for (int i = 0; i < N; i++) {
arr[i] = -1;
}
// If the absolute difference between A and B is
// greater 1 or A+B is greater than N-2, then return -1
if (abs(A - B) > 1 || A + B > N - 2) {
cout << -1;
}
else {
if (A > B) {
// Initialize maxValue with N
int maxValue = N;
// Create a maxima's
for (int i = 1; i < N - 1 && A > 0; i += 2) {
arr[i] = maxValue;
maxValue--;
A--;
}
// Fill other elements in decreasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = maxValue;
maxValue--;
}
}
}
else if (A < B) {
// Initialize minValue with 1
int minValue = 1;
// Create B minima's
for (int i = 1; i < N - 1 && B > 0; i += 2) {
arr[i] = minValue;
minValue++;
B--;
}
// Fill other elements in increasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = minValue;
minValue++;
}
}
}
else if (A == B) {
// Initialize maxValue with n and minValue with
// 1
int minValue = 1, maxValue = N;
arr[0] = minValue;
minValue++;
// Initialize fill equal number of minima and
// maximas
for (int i = 1; i < N - 1 && A > 0; i += 2) {
arr[i] = maxValue;
arr[i + 1] = minValue;
A--;
maxValue--;
minValue++;
}
// Fill the rest in increasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = minValue;
minValue++;
}
}
}
// Print the output
for (int i = 0; i < N; i++) {
cout << arr[i] << " ";
}
}
cout << endl;
}
// Driver Code
int main()
{
int N = 6, A = 2, B = 1;
findPermutation(N, A, B);
return 0;
}
Java
// Java program for the above approach
class GFG{
// Function to find the permutation of 1 to N numbers
// having A minimas and B maximas
static void findPermutation(int N, int A, int B)
{
// Create the result array
int []arr = new int[N];
for (int i = 0; i < N; i++) {
arr[i] = -1;
}
// If the absolute difference between A and B is
// greater 1 or A+B is greater than N-2, then return -1
if (Math.abs(A - B) > 1 || A + B > N - 2) {
System.out.print(-1);
}
else {
if (A > B) {
// Initialize maxValue with N
int maxValue = N;
// Create a maxima's
for (int i = 1; i < N - 1 && A > 0; i += 2) {
arr[i] = maxValue;
maxValue--;
A--;
}
// Fill other elements in decreasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = maxValue;
maxValue--;
}
}
}
else if (A < B) {
// Initialize minValue with 1
int minValue = 1;
// Create B minima's
for (int i = 1; i < N - 1 && B > 0; i += 2) {
arr[i] = minValue;
minValue++;
B--;
}
// Fill other elements in increasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = minValue;
minValue++;
}
}
}
else if (A == B) {
// Initialize maxValue with n and minValue with
// 1
int minValue = 1, maxValue = N;
arr[0] = minValue;
minValue++;
// Initialize fill equal number of minima and
// maximas
for (int i = 1; i < N - 1 && A > 0; i += 2) {
arr[i] = maxValue;
arr[i + 1] = minValue;
A--;
maxValue--;
minValue++;
}
// Fill the rest in increasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = minValue;
minValue++;
}
}
}
// Print the output
for (int i = 0; i < N; i++) {
System.out.print(arr[i]+ " ");
}
}
System.out.println();
}
// Driver Code
public static void main(String[] args)
{
int N = 6, A = 2, B = 1;
findPermutation(N, A, B);
}
}
// This code is contributed by 29AjayKumar
Python3
# Python 3 program for the above approach
# Function to find the permutation of 1 to N numbers
# having A minimas and B maximas
def findPermutation(N, A, B):
# Create the result array
arr = [0]*(N)
for i in range(N):
arr[i] = -1
# If the absolute difference between A and B is
# greater 1 or A+B is greater than N-2, then return -1
if (abs(A - B) > 1 or A + B > N - 2):
print(-1)
else:
if (A > B):
# Initialize maxValue with N
maxValue = N
# Create a maxima's
i = 1
while i < N - 1 and A > 0:
arr[i] = maxValue
maxValue -= 1
A -= 1
i += 2
# Fill other elements in decreasing order
for i in range(N):
if (arr[i] == -1):
arr[i] = maxValue
maxValue -= 1
elif (A < B):
# Initialize minValue with 1
minValue = 1
# Create B minima's
i = 1
while i < N - 1 and B > 0:
arr[i] = minValue
minValue += 1
B -= 1
i += 2
# Fill other elements in increasing order
for i in range(N):
if (arr[i] == -1):
arr[i] = minValue
minValue += 1
elif (A == B):
# Initialize maxValue with n and minValue with
# 1
minValue = 1
maxValue = N
arr[0] = minValue
minValue += 1
# Initialize fill equal number of minima and
# maximas
i = 1
while i < N - 1 and A > 0:
arr[i] = maxValue
arr[i + 1] = minValue
A -= 1
maxValue -= 1
minValue += 1
i += 2
# Fill the rest in increasing order
for i in range(N):
if (arr[i] == -1):
arr[i] = minValue
minValue += 1
# Print the output
for i in range(N):
print(arr[i], end=" ")
print()
# Driver Code
if __name__ == "__main__":
N = 6
A = 2
B = 1
findPermutation(N, A, B)
# This code is contributed by ukasp.
C#
// C# program for the above approach
using System;
class GFG{
// Function to find the permutation of 1 to N numbers
// having A minimas and B maximas
static void findPermutation(int N, int A, int B)
{
// Create the result array
int []arr = new int[N];
for (int i = 0; i < N; i++) {
arr[i] = -1;
}
// If the absolute difference between A and B is
// greater 1 or A+B is greater than N-2, then return -1
if (Math.Abs(A - B) > 1 || A + B > N - 2) {
Console.Write(-1);
}
else {
if (A > B) {
// Initialize maxValue with N
int maxValue = N;
// Create a maxima's
for (int i = 1; i < N - 1 && A > 0; i += 2) {
arr[i] = maxValue;
maxValue--;
A--;
}
// Fill other elements in decreasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = maxValue;
maxValue--;
}
}
}
else if (A < B) {
// Initialize minValue with 1
int minValue = 1;
// Create B minima's
for (int i = 1; i < N - 1 && B > 0; i += 2) {
arr[i] = minValue;
minValue++;
B--;
}
// Fill other elements in increasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = minValue;
minValue++;
}
}
}
else if (A == B) {
// Initialize maxValue with n and minValue with
// 1
int minValue = 1, maxValue = N;
arr[0] = minValue;
minValue++;
// Initialize fill equal number of minima and
// maximas
for (int i = 1; i < N - 1 && A > 0; i += 2) {
arr[i] = maxValue;
arr[i + 1] = minValue;
A--;
maxValue--;
minValue++;
}
// Fill the rest in increasing order
for (int i = 0; i < N; i++) {
if (arr[i] == -1) {
arr[i] = minValue;
minValue++;
}
}
}
// Print the output
for (int i = 0; i < N; i++) {
Console.Write(arr[i]+ " ");
}
}
Console.Write("\n");
}
// Driver Code
public static void Main()
{
int N = 6, A = 2, B = 1;
findPermutation(N, A, B);
}
}
// This code is contributed by Samim Hossain Mondal.
Javascript
输出
4 6 3 5 2 1
时间复杂度: O(N)
辅助空间: O(N)