用 K 个求逆求 N 个自然数的排列
给定两个整数N和K ,任务是找到前N个自然数恰好有K个反转的排列。
例子 :
Input: N = 5, K = 4
Output: 5 1 2 3 4
Explanation: In the above permutation P, the pairs (i, j) such that i < j and P[i] > P[j] are (0, 1), (0, 2), (0, 3), and (0, 4). Hence, the number of inversions in the above permutation is 4 which is the required value.
Input: N = 3, K = 4
Output: -1
Explanation: No possible permutation of first 3 natural numbers has exactly 4 inversions.
方法:给定的问题可以通过贪心方法来解决。可以观察到,如果将N个元素的数组的最大元素分配在第 i个位置,它将贡献(N – i)次反转。使用此观察结果,请按照以下步骤解决给定问题:
- 检查条件是否K > 可能的最大反转次数(即 N*(N-1)/2)。如果为真,则返回-1 。
- 创建一个变量curr ,它跟踪数组的当前最大元素。最初curr = N 。
- 创建一个数组p[] ,它跟踪当前的排列。
- 使用 [1, N] 范围内的变量i进行迭代,如果K > (curr – i) ,则将 curr 分配给数组的当前位置并从K中减去(curr – i) 。此外,将curr的值减 1。
- 如果K > (curr – i)为假,则将K+1分配给当前索引,并在数组p[]中按升序分配剩余的整数。
下面是上述方法的实现:
C++
// C++ program of the above approach
#include
using namespace std;
// Function to fint the permutation of
// N natural numbers with k inversions
void findPermutation(int n, int k)
{
// Stores the maximum number of inversions
int max_inv = (n * (n - 1)) / 2;
// If required inversions are more that max
if (k > max_inv) {
cout << "-1";
return;
}
// Stores the final permutation
int p[n + 1];
// Keep track of the current max element
// in the permutation
int curr = n;
int i = 1;
// Loop to iterate through the array
for (i = 1; i <= n; i++) {
// Set current element as ith element
// in order to increase n-i inversions
// in the given permutation
if (k >= n - i) {
p[i] = curr;
curr--;
k -= (n - i);
}
// Otherwise set (k+1) element at ith index
// ans assign the remaining indices
else {
// If the remaining inversion count is
// greater than 0
if (k == 0) {
i--;
}
else {
p[i] = k + 1;
}
// Set the next index as 1
p[i + 1] = 1;
// Loop to assign the remaining indices
for (int j = i + 2; j <= n; j++) {
p[j] = p[j - 1] + 1;
// If current element already occured
if (p[i] == p[j]) {
p[j]++;
}
}
break;
}
}
// Print Answer
for (int j = 1; j <= n; j++) {
cout << p[j] << " ";
}
}
// Driver code
int main()
{
int n = 5;
int k = 4;
findPermutation(n, k);
return 0;
}
Java
// Java program for the above approach
import java.io.*;
class GFG {
// Function to fint the permutation of
// N natural numbers with k inversions
static void findPermutation(int n, int k)
{
// Stores the maximum number of inversions
int max_inv = (n * (n - 1)) / 2;
// If required inversions are more that max
if (k > max_inv) {
System.out.println("-1");
return;
}
// Stores the final permutation
int [] p = new int[n+1];
// Keep track of the current max element
// in the permutation
int curr = n;
int i = 1;
// Loop to iterate through the array
for (i = 1; i <= n; i++) {
// Set current element as ith element
// in order to increase n-i inversions
// in the given permutation
if (k >= n - i) {
p[i] = curr;
curr--;
k -= (n - i);
}
// Otherwise set (k+1) element at ith index
// ans assign the remaining indices
else {
// If the remaining inversion count is
// greater than 0
if (k == 0) {
i--;
}
else {
p[i] = k + 1;
}
// Set the next index as 1
p[i + 1] = 1;
// Loop to assign the remaining indices
for (int j = i + 2; j <= n; j++) {
p[j] = p[j - 1] + 1;
// If current element already occured
if (p[i] == p[j]) {
p[j]++;
}
}
break;
}
}
// Print Answer
for (int j = 1; j <= n; j++) {
System.out.print(p[j] + " ");
}
}
// Driver code
public static void main (String[] args) {
int n = 5;
int k = 4;
findPermutation(n, k);
}
}
// This code is contributed by Potta Lokesh
Python3
# python program of the above approach
# Function to fint the permutation of
# N natural numbers with k inversions
def findPermutation(n, k):
# Stores the maximum number of inversions
max_inv = (n * (n - 1)) / 2
# If required inversions are more that max
if (k > max_inv):
print("-1")
return
# Stores the final permutation
p = [0 for _ in range(n + 1)]
# Keep track of the current max element
# in the permutation
curr = n
i = 1
# Loop to iterate through the array
for i in range(1, n+1):
# Set current element as ith element
# in order to increase n-i inversions
# in the given permutation
if (k >= n - i):
p[i] = curr
curr -= 1
k -= (n - i)
# Otherwise set (k+1) element at ith index
# ans assign the remaining indices
else:
# If the remaining inversion count is
# greater than 0
if (k == 0):
i -= 1
else:
p[i] = k + 1
# Set the next index as 1
p[i + 1] = 1
# Loop to assign the remaining indices
for j in range(i+2, n+1):
p[j] = p[j - 1] + 1
# If current element already occured
if (p[i] == p[j]):
p[j] += 1
break
# Print Answer
for j in range(1, n+1):
print(p[j], end=" ")
# Driver code
if __name__ == "__main__":
n = 5
k = 4
findPermutation(n, k)
# This code is contributed by rakeshsahni
Javascript
C#
// C# program for the above approach
using System;
public class GFG {
// Function to fint the permutation of
// N natural numbers with k inversions
static void findPermutation(int n, int k)
{
// Stores the maximum number of inversions
int max_inv = (n * (n - 1)) / 2;
// If required inversions are more that max
if (k > max_inv) {
Console.WriteLine("-1");
return;
}
// Stores the final permutation
int [] p = new int[n+1];
// Keep track of the current max element
// in the permutation
int curr = n;
int i = 1;
// Loop to iterate through the array
for (i = 1; i <= n; i++) {
// Set current element as ith element
// in order to increase n-i inversions
// in the given permutation
if (k >= n - i) {
p[i] = curr;
curr--;
k -= (n - i);
}
// Otherwise set (k+1) element at ith index
// ans assign the remaining indices
else {
// If the remaining inversion count is
// greater than 0
if (k == 0) {
i--;
}
else {
p[i] = k + 1;
}
// Set the next index as 1
p[i + 1] = 1;
// Loop to assign the remaining indices
for (int j = i + 2; j <= n; j++) {
p[j] = p[j - 1] + 1;
// If current element already occured
if (p[i] == p[j]) {
p[j]++;
}
}
break;
}
}
// Print Answer
for (int j = 1; j <= n; j++) {
Console.Write(p[j] + " ");
}
}
// Driver code
public static void Main (string[] args) {
int n = 5;
int k = 4;
findPermutation(n, k);
}
}
// This code is contributed by AnkThon
输出
5 1 2 3 4
时间复杂度: O(N)
辅助空间: O(N)