给定两个整数N和K ,无需使用STL函数即可找到从1到N的第K个排列数。
注意:假设输入使得N数的Kth置换始终是可能的。
例子:
Input: N = 3, K = 4
Output: 231
Explanation:
The ordered list of permutation sequence from integer 1 to 3 is : 123, 132, 213, 231, 312, 321. So, the 4th permutation sequence is “231”.
Input: N = 2, K = 1
Output: 12
Explanation:
For n = 2, only 2 permutations are possible 12 21. So, the 1st permutation sequence is “12”.
天真的方法:
为了解决上述问题,简单的方法是找到所有排列序列并输出其中的第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时,我们不再需要查找实际的阶乘值,因为:
k / n_actual_factorial_value = 0
and k / n_partial_factorial_value = 0
when partial_factorial_value > 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