📜  找出前N个自然数的第K个置换序列

📅  最后修改于: 2021-06-25 12:24:05             🧑  作者: Mango

给定两个整数N和K ,无需使用STL函数即可找到从1到N的第K个排列数。
注意:假设输入使得N数的Kth置换始终是可能的。

例子:

天真的方法:
为了解决上述问题,简单的方法是找到所有排列序列并输出其中的第k个。但是此方法效率不高,需要花费更多时间,因此可以对其进行优化。

高效方法:
为了优化上述方法,可以观察到k的值可以直接用于在序列的每个索引处找到数字。

  • n个长度序列的第一个位置被从1到n的每个数字正好占据n! / n为(n-1)!次数并按升序排列。因此,第k个序列的第一个位置将被索引= k /(n-1)处的数字占据! (根据基于1的索引)。
  • 当前找到的数字无法再出现,因此将其从原始n个数字中删除,现在问题减少到找到其余n-1个数字的(k%(n-1)!)个置换序列。
  • 可以重复此过程,直到只剩下一个数字,该数字将被放置在最后一个1长度序列的第一个位置。
  • 与k相比,此处涉及的阶乘值可能非常大。因此,避免对如此大的阶乘进行完整计算的技巧是,乘积n *(n-1)*…大于k时,我们不再需要查找实际的阶乘值,因为:

下面是上述方法的实现:

C++
// C++ program to Find the kth Permutation
// Sequence of first n natural numbers
 
#include 
using namespace std;
 
// Function to find the index of number
// at first position of
// kth sequence of set of size n
int findFirstNumIndex(int& k, int n)
{
 
    if (n == 1)
        return 0;
    n--;
 
    int first_num_index;
    // n_actual_fact = n!
    int n_partial_fact = n;
 
    while (k >= n_partial_fact
           && n > 1) {
        n_partial_fact
            = n_partial_fact
              * (n - 1);
        n--;
    }
 
    // First position of the
    // kth sequence will be
    // occupied by the number present
    // at index = k / (n-1)!
    first_num_index = k / n_partial_fact;
 
    k = k % n_partial_fact;
 
    return first_num_index;
}
 
// Function to find the
// kth permutation of n numbers
string findKthPermutation(int n, int k)
{
    // Store final answer
    string ans = "";
 
    set s;
 
    // Insert all natural number
    // upto n in set
    for (int i = 1; i <= n; i++)
        s.insert(i);
 
    set::iterator itr;
 
    // Mark the first position
    itr = s.begin();
 
    // subtract 1 to get 0 based indexing
    k = k - 1;
 
    for (int i = 0; i < n; i++) {
 
        int index
            = findFirstNumIndex(k, n - i);
 
        advance(itr, index);
 
        // itr now points to the
        // number at index in set s
        ans += (to_string(*itr));
 
        // remove current number from the set
        s.erase(itr);
 
        itr = s.begin();
    }
    return ans;
}
 
// Driver code
int main()
{
 
    int n = 3, k = 4;
 
    string kth_perm_seq
        = findKthPermutation(n, k);
 
    cout << kth_perm_seq << endl;
 
    return 0;
}


Java
// Java program to Find
// the kth Permutation
// Sequence of first
// n natural numbers
import java.util.*;
class GFG{
 
// Function to find the index of
// number at first position of
// kth sequence of set of size n
static int findFirstNumIndex(int k,
                             int n)
{
  if (n == 1)
    return 0;
  n--;
 
  int first_num_index;
   
  // n_actual_fact = n!
  int n_partial_fact = n;
 
  while (k >= n_partial_fact && n > 1)
  {
    n_partial_fact = n_partial_fact *
                     (n - 1);
    n--;
  }
 
  // First position of the
  // kth sequence will be
  // occupied by the number present
  // at index = k / (n-1)!
  first_num_index = k / n_partial_fact;
 
  k = k % n_partial_fact;
  return first_num_index;
}
 
// Function to find the
// kth permutation of n numbers
static String findKthPermutation(int n,
                                 int k)
{
  // Store final answer
  String ans = "";
 
  HashSet s = new HashSet<>();
 
  // Insert all natural number
  // upto n in set
  for (int i = 1; i <= n; i++)
    s.add(i);
 
  Vector v = new Vector<>();
  v.addAll(s);
 
  // Mark the first position
  int itr = v.elementAt(0);
   
  // Subtract 1 to
  // get 0 based
  // indexing
  k = k - 1;
 
  for (int i = 0; i < n; i++)
  {
    int index = findFirstNumIndex(k,
                                  n - i);
     
    // itr now points to the
    // number at index in set s
    if(index < v.size())
    {
      ans += ((v.elementAt(index).toString()));
      v.remove(index);
    }
    else
      ans += String.valueOf(itr + 2);
 
    // Remove current number
    // from the set
    itr = v.elementAt(0);
  }
  return ans;
}
 
// Driver code
public static void main(String[] args)
{
  int n = 3, k = 4;
  String kth_perm_seq = findKthPermutation(n, k);
  System.out.print(kth_perm_seq + "\n");
}
}
 
// This code is contributed by Rajput-Ji


Python3
# Python3 program to find the kth permutation
# Sequence of first n natural numbers
 
# Function to find the index of number
# at first position of kth sequence of
# set of size n
def findFirstNumIndex(k, n):
 
    if (n == 1):
        return 0, k
         
    n -= 1
 
    first_num_index = 0
     
    # n_actual_fact = n!
    n_partial_fact = n
 
    while (k >= n_partial_fact and n > 1):
        n_partial_fact = n_partial_fact * (n - 1)
        n -= 1
 
    # First position of the kth sequence
    # will be occupied by the number present
    # at index = k / (n-1)!
    first_num_index = k // n_partial_fact
 
    k = k % n_partial_fact
 
    return first_num_index, k
 
# Function to find the
# kth permutation of n numbers
def findKthPermutation(n, k):
 
    # Store final answer
    ans = ""
 
    s = set()
 
    # Insert all natural number
    # upto n in set
    for i in range(1, n + 1):
        s.add(i)
 
    # Subtract 1 to get 0 based indexing
    k = k - 1
 
    for i in range(n):
 
        # Mark the first position
        itr = list(s)
 
        index, k = findFirstNumIndex(k, n - i)
 
        # itr now points to the
        # number at index in set s
        ans += str(itr[index])
 
        # remove current number from the set
        itr.pop(index)
         
        s = set(itr)
     
    return ans
 
# Driver code
if __name__=='__main__':
 
    n = 3
    k = 4
     
    kth_perm_seq = findKthPermutation(n, k)
 
    print(kth_perm_seq)
 
# This code is contributed by rutvik_56


C#
// C# program to Find
// the kth Permutation
// Sequence of first
// n natural numbers
using System;
using System.Collections.Generic;
class GFG{
 
// Function to find the index of
// number at first position of
// kth sequence of set of size n
static int findFirstNumIndex(int k,
                             int n)
{
  if (n == 1)
    return 0;
  n--;
 
  int first_num_index;
 
  // n_actual_fact = n!
  int n_partial_fact = n;
 
  while (k >= n_partial_fact && n > 1)
  {
    n_partial_fact = n_partial_fact *
                     (n - 1);
    n--;
  }
 
  // First position of the
  // kth sequence will be
  // occupied by the number present
  // at index = k / (n-1)!
  first_num_index = k / n_partial_fact;
 
  k = k % n_partial_fact;
  return first_num_index;
}
 
// Function to find the
// kth permutation of n numbers
static String findKthPermutation(int n,
                                 int k)
{
  // Store readonly answer
  String ans = "";
 
  HashSet s = new HashSet();
 
  // Insert all natural number
  // upto n in set
  for (int i = 1; i <= n; i++)
    s.Add(i);
 
  List v = new List(s);
 
  // Mark the first position
  int itr = v[0];
 
  // Subtract 1 to
  // get 0 based
  // indexing
  k = k - 1;
 
  for (int i = 0; i < n; i++)
  {
    int index = findFirstNumIndex(k, n - i);
 
    // itr now points to the
    // number at index in set s
    if(index < v.Count)
    {
      ans += ((v[index].ToString()));
      v.RemoveAt(index);
    }
    else
      ans += String.Join("", itr + 2);
 
    // Remove current number
    // from the set
    itr = v[0];
  }
  return ans;
}
 
// Driver code
public static void Main(String[] args)
{
  int n = 3, k = 4;
  String kth_perm_seq = findKthPermutation(n, k);
  Console.Write(kth_perm_seq + "\n");
}
}
 
// This code is contributed by Rajput-Ji


输出:
231