📜  查找具有 X 局部最大值(峰)和 Y 局部最小值(谷)的数字 1 到 N 的排列

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

查找具有 X 局部最大值(峰)和 Y 局部最小值(谷)的数字 1 到 N 的排列

给定三个整数NAB ,任务是找到从1N的成对不同数字的排列,该排列恰好具有“A”局部最小值和“B”局部最大值。

  • 局部最小值被定义为小于其相邻元素的元素。
  • 局部最大值定义为大于其相邻元素的元素。
  • 整个排列的第一个和最后一个元素永远不能是局部最小值或最大值。

如果不存在这样的排列,则打印-1

例子 :

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

  • 生成从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++) {
        // 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!)

有效方法(贪婪方法):

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

  • 由于整个排列的第一个和最后一个元素不能是最大值或最小值,因此最大值和最小值的总数必须小于或等于N-2 。所以如果(A + B > N -2) ,打印-1
  • 此外,不能有两个连续的最小值或最大值。两个连续的最大值之间必须有一个最小值,两个连续的最小值之间必须有一个最大值。因此,最小值和最大值的总数之间的绝对差必须小于或等于 1。因此,如果AB之间的绝对差超过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 和maxValueN 。用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)