Given two integers N and K, find the Kth permutation sequence of numbers from 1 to N without using STL function.
Note: Assume that the inputs are such that Kth permutation of N number is always possible.
Examples:
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”.
Naive Approach:
To solve the problem mentioned above the simple approach is to find all permutation sequences and output the kth out of them. But this method is not so efficient and takes more time, hence it can be optimized.
C++
#include <bits/stdc++.h>
using namespace std;
void generate_permutations(string& str, int idx, vector<string>& result) {
if (idx == str.size()) {
result.push_back(str);
return ;
}
for ( int i = idx; i < str.size(); i++) {
swap(str[i], str[idx]);
generate_permutations(str, idx + 1, result);
swap(str[i], str[idx]);
}
}
string findKthPermutation( int n, int k) {
string str = "" ;
vector<string> result;
for ( int i = 1; i <= n; i++) {
str.push_back(i + '0' );
}
generate_permutations(str, 0, result);
sort(result.begin(), result.end());
return result[k-1];
}
int main() {
int n = 3, k = 4;
string kth_perm_seq = findKthPermutation(n, k);
cout << kth_perm_seq << endl;
return 0;
}
|
Java
import java.util.*;
class GFG {
public static void main(String[] args)
{
int n = 3 , k = 4 ;
String kth_perm_seq = findKthPermutation(n, k);
System.out.println(kth_perm_seq);
}
static char [] swap(String s, int i, int j)
{
char [] ch = s.toCharArray();
char temp = ch[i];
ch[i] = ch[j];
ch[j] = temp;
return ch;
}
static void generate_permutations(String str, int idx,
List<String> result)
{
if (idx == str.length()) {
result.add(str);
return ;
}
for ( int i = idx; i < str.length(); i++) {
str = new String(swap(str, i, idx));
generate_permutations(str, idx + 1 , result);
str = new String(swap(str, i, idx));
}
}
static String findKthPermutation( int n, int k)
{
String str = "" ;
List<String> result = new ArrayList<String>();
for ( int i = 1 ; i <= n; i++) {
str += i;
}
generate_permutations(str, 0 , result);
Collections.sort(result);
return result.get(k - 1 );
}
}
|
Python3
def generate_permutations(ch, idx, result):
if idx = = len (ch):
str1 = ""
result.append(str1.join(ch))
return
for i in range (idx, len (ch)):
ch[i], ch[idx] = ch[idx], ch[i]
generate_permutations(ch, idx + 1 , result)
ch[i], ch[idx] = ch[idx], ch[i]
def findKthPermutation(n, k):
s = ""
result = []
for i in range ( 1 , n + 1 ):
s + = str (i)
ch = [ * s]
generate_permutations(ch, 0 , result)
result.sort()
return result[k - 1 ]
if __name__ = = "__main__" :
n = 3
k = 4
kth_perm_seq = findKthPermutation(n, k)
print (kth_perm_seq)
|
C#
using System;
using System.Collections.Generic;
class Program {
static void Main( string [] args)
{
int n = 3, k = 4;
string kth_perm_seq = findKthPermutation(n, k);
Console.WriteLine(kth_perm_seq);
}
static char [] swap( string s, int i, int j)
{
char [] ch = s.ToCharArray();
char temp = ch[i];
ch[i] = ch[j];
ch[j] = temp;
return ch;
}
static void generate_permutations( string str, int idx,
List< string > result)
{
if (idx == str.Length) {
result.Add(str);
return ;
}
for ( int i = idx; i < str.Length; i++) {
str = new string (swap(str, i, idx));
generate_permutations(str, idx + 1, result);
str = new string (swap(str, i, idx));
}
}
static string findKthPermutation( int n, int k)
{
string str = "" ;
List< string > result = new List< string >();
for ( int i = 1; i <= n; i++) {
str += i;
}
generate_permutations(str, 0, result);
result.Sort();
return result[k - 1];
}
}
|
Javascript
<script>
function swap(ch, i, j) {
var temp = ch[i];
ch[i] = ch[j];
ch[j] = temp;
return ch;
}
function generate_permutations(ch, idx, result) {
if (idx == ch.length) {
result.push(ch.join( "" ));
return ;
}
for ( var i = idx; i < ch.length; i++) {
swap(ch, i, idx);
generate_permutations(ch, idx + 1, result);
swap(ch, i, idx);
}
}
function findKthPermutation(n, k) {
var s = "" ;
var result = [];
for ( var i = 1; i <= n; i++) {
s += i;
}
var ch = s.split( "" );
generate_permutations(ch, 0, result);
result.sort();
return result[k - 1];
}
var n = 3;
var k = 4;
var kth_perm_seq = findKthPermutation(n, k);
console.log(kth_perm_seq);
</script>
|
Time Complexity = O((N! * N) + (N! * log N!))
Auxiliary Space = O(N) to store all permutations
Efficient Approach:
To optimize the above method mentioned above, observe that the value of k can be directly used to find the number at each index of the sequence.
- The first position of an n length sequence is occupied by each of the numbers from 1 to n exactly n! / n that is (n-1)! number of times and in ascending order. So the first position of the kth sequence will be occupied by the number present at index = k / (n-1)! (according to 1-based indexing).
- The currently found number can not occur again so it is removed from the original n numbers and now the problem reduces to finding the ( k % (n-1)! )th permutation sequence of the remaining n-1 numbers.
- This process can be repeated until we have only one number left which will be placed in the first position of the last 1-length sequence.
- The factorial values involved here can be very large as compared to k. So, the trick used to avoid the full computation of such large factorials is that as soon as the product n * (n-1) * … becomes greater than k, we no longer need to find the actual factorial value because:
k / n_actual_factorial_value = 0
and k / n_partial_factorial_value = 0
when partial_factorial_value > k
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int findFirstNumIndex( int & k, int n)
{
if (n == 1)
return 0;
n--;
int first_num_index;
int n_partial_fact = n;
while (k >= n_partial_fact
&& n > 1) {
n_partial_fact
= n_partial_fact
* (n - 1);
n--;
}
first_num_index = k / n_partial_fact;
k = k % n_partial_fact;
return first_num_index;
}
string findKthPermutation( int n, int k)
{
string ans = "" ;
set< int > s;
for ( int i = 1; i <= n; i++)
s.insert(i);
set< int >::iterator itr;
itr = s.begin();
k = k - 1;
for ( int i = 0; i < n; i++) {
int index
= findFirstNumIndex(k, n - i);
advance(itr, index);
ans += (to_string(*itr));
s.erase(itr);
itr = s.begin();
}
return ans;
}
int main()
{
int n = 3, k = 4;
string kth_perm_seq
= findKthPermutation(n, k);
cout << kth_perm_seq << endl;
return 0;
}
|
Java
import java.util.*;
class GFG{
static int findFirstNumIndex( int k,
int n)
{
if (n == 1 )
return 0 ;
n--;
int first_num_index;
int n_partial_fact = n;
while (k >= n_partial_fact && n > 1 )
{
n_partial_fact = n_partial_fact *
(n - 1 );
n--;
}
first_num_index = k / n_partial_fact;
k = k % n_partial_fact;
return first_num_index;
}
static String findKthPermutation( int n,
int k)
{
String ans = "" ;
HashSet<Integer> s = new HashSet<>();
for ( int i = 1 ; i <= n; i++)
s.add(i);
Vector<Integer> v = new Vector<>();
v.addAll(s);
int itr = v.elementAt( 0 );
k = k - 1 ;
for ( int i = 0 ; i < n; i++)
{
int index = findFirstNumIndex(k,
n - i);
if (index < v.size())
{
ans += ((v.elementAt(index).toString()));
v.remove(index);
}
else
ans += String.valueOf(itr + 2 );
itr = v.elementAt( 0 );
}
return ans;
}
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" );
}
}
|
Python3
def findFirstNumIndex(k, n):
if (n = = 1 ):
return 0 , k
n - = 1
first_num_index = 0
n_partial_fact = n
while (k > = n_partial_fact and n > 1 ):
n_partial_fact = n_partial_fact * (n - 1 )
n - = 1
first_num_index = k / / n_partial_fact
k = k % n_partial_fact
return first_num_index, k
def findKthPermutation(n, k):
ans = ""
s = set ()
for i in range ( 1 , n + 1 ):
s.add(i)
k = k - 1
for i in range (n):
itr = list (s)
index, k = findFirstNumIndex(k, n - i)
ans + = str (itr[index])
itr.pop(index)
s = set (itr)
return ans
if __name__ = = '__main__' :
n = 3
k = 4
kth_perm_seq = findKthPermutation(n, k)
print (kth_perm_seq)
|
C#
using System;
using System.Collections.Generic;
class GFG{
static int findFirstNumIndex( int k,
int n)
{
if (n == 1)
return 0;
n--;
int first_num_index;
int n_partial_fact = n;
while (k >= n_partial_fact && n > 1)
{
n_partial_fact = n_partial_fact *
(n - 1);
n--;
}
first_num_index = k / n_partial_fact;
k = k % n_partial_fact;
return first_num_index;
}
static String findKthPermutation( int n,
int k)
{
String ans = "" ;
HashSet< int > s = new HashSet< int >();
for ( int i = 1; i <= n; i++)
s.Add(i);
List< int > v = new List< int >(s);
int itr = v[0];
k = k - 1;
for ( int i = 0; i < n; i++)
{
int index = findFirstNumIndex(k, n - i);
if (index < v.Count)
{
ans += ((v[index].ToString()));
v.RemoveAt(index);
}
else
ans += String.Join( "" , itr + 2);
itr = v[0];
}
return ans;
}
public static void Main(String[] args)
{
int n = 3, k = 4;
String kth_perm_seq = findKthPermutation(n, k);
Console.Write(kth_perm_seq + "\n" );
}
}
|
Javascript
function findFirstNumIndex(k, n)
{
if (n == 1)
return [0, k]
n -= 1
let first_num_index = 0
let n_partial_fact = n
while (k >= n_partial_fact && n > 1)
{
n_partial_fact = n_partial_fact * (n - 1)
n -= 1
}
first_num_index = Math.floor(k / n_partial_fact)
k = k % n_partial_fact
return [first_num_index, k]
}
function findKthPermutation(n, k)
{
let ans = ""
let s = new Set()
for (let i = 1; i <= n; i++)
s.add(i)
k = k - 1
for (let i = 0; i <n; i++)
{
let itr = Array.from(s)
let res = findFirstNumIndex(k, n - i)
let index = res[0]
k = res[1]
ans += (itr[index])
itr.splice(index, 1)
s = new Set(itr)
}
return ans
}
let n = 3
let k = 4
let kth_perm_seq = findKthPermutation(n, k)
console.log(kth_perm_seq)
|
Time Complexity : O(N^2)
Auxiliary Space : O(N)
Most Efficient Approach Using Combinatorics:
The base idea is that the first character can be found knowing that it has repeated (n-1)! times, given a particular value of n.
For example, given the base case “1234” with n = 4, we can list out all the permutations that starts with ‘1’:
1234
1324
1342
1243
1423
1432
As we can see, there are 6 cases in total where we have n = 4 that starts with ‘1’. That is because there are exactly (n-1)! = (4-1)! = 3! = 6 unique cases with the characters after the first one.
With this knowledge, we can deal with the problem recursively:
Given a particular value of n, and k, we can compute the first character in the set (i.e., {1,2,3,4,…,n}) of characters in increasing order by:
pos = k / factorial(n-1)
where pos is the index to the character in the set we want.
Then we have to remove the character at index pos from the set, since we can only use each character once.
What about the next iteration? Now that we have the desired character for n, we can turn to n-1, since we have knocked one of the n characters down, so n-1 left to go.
But what about k? Well, since we have considered a total number of k * factorial(n-1) permutations, we are left with k %= factorial(n-1), and that is going to be our new k for the next iteration.
An example for this, back to our case of n=4 above, imagine we have input k = 21. Now, we have already established there are 6 unique cases for the remaining n-1 characters for EACH of the unique character for the first one:
Looking at first character:
1 … (6 permutations)
2 … (6 permutations)
3 … (6 permutations)
Figured out first character is ‘4’.
Figured out first character, moving onto second characters, we have already considered 18 cases, so left with k %= factorial(n-1) = 21 %= 6 = 3 left.
C++
#include <bits/stdc++.h>
using namespace std;
int fact[10] = {1,1,2,6,24,120,720,5040,40320,362880};
void permutation( int n, int k, set< int >&nums, string &str)
{
if (n==0) return ;
int val;
if (k<=1 || k<=fact[n-1])
{
val = k==0 ? *nums.rbegin() : *nums.begin();
}
else
{
int index = k/fact[n-1];
k = k %fact[n-1];
if (k==0)index--;
val = *next(nums.begin(),index);
}
str+= to_string(val);
nums.erase(val);
return permutation(n-1,k,nums,str);
}
string getPermutation( int n, int k) {
set< int >nums;
for ( int i=1;i<=n;i++)nums.insert(i);
string str = "" ;
permutation(n,k,nums,str);
return str;
}
int main()
{
int n = 3, k = 4;
string kth_perm_seq
= getPermutation(n, k);
cout << kth_perm_seq << endl;
return 0;
}
|
Java
import java.util.TreeSet;
public class KthPermutation {
static int [] fact = { 1 , 1 , 2 , 6 , 24 , 120 , 720 , 5040 , 40320 , 362880 };
static void permutation( int n, int k, TreeSet<Integer> nums, StringBuilder str) {
if (n == 0 )
return ;
int val;
if (k <= 1 || k <= fact[n - 1 ]) {
val = (k == 0 ) ? nums.last() : nums.first();
} else {
int index = k / fact[n - 1 ];
k = k % fact[n - 1 ];
if (k == 0 )
index--;
val = ( int ) nums.toArray()[index];
}
str.append(val);
nums.remove(val);
permutation(n - 1 , k, nums, str);
}
static String getPermutation( int n, int k) {
TreeSet<Integer> nums = new TreeSet<>();
for ( int i = 1 ; i <= n; i++)
nums.add(i);
StringBuilder str = new StringBuilder();
permutation(n, k, nums, str);
return str.toString();
}
public static void main(String[] args) {
int n = 3 , k = 4 ;
String kth_perm_seq = getPermutation(n, k);
System.out.println(kth_perm_seq);
}
}
|
Python3
fact = [ 1 , 1 , 2 , 6 , 24 , 120 , 720 , 5040 , 40320 , 362880 ]
def permutation(n, k, nums, result_str):
if n = = 0 :
return result_str
if k < = 1 or k < = fact[n - 1 ]:
val = nums[ - 1 ] if k = = 0 else nums[ 0 ]
else :
index = k / / fact[n - 1 ]
k = k % fact[n - 1 ]
if k = = 0 :
index - = 1
val = nums[index]
result_str + = str (val)
nums.remove(val)
return permutation(n - 1 , k, nums, result_str)
def get_permutation(n, k):
nums = list ( range ( 1 , n + 1 ))
result_str = ""
return permutation(n, k, nums, result_str)
if __name__ = = "__main__" :
n = 3
k = 4
kth_perm_seq = get_permutation(n, k)
print (kth_perm_seq)
|
C#
using System;
using System.Linq;
using System.Collections.Generic;
public class KthPermutation
{
static int [] fact = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };
static void Permutation( int n, int k, SortedSet< int > nums, System.Text.StringBuilder str)
{
if (n == 0)
return ;
int val;
if (k <= 1 || k <= fact[n - 1])
{
val = (k == 0) ? nums.Max : nums.Min;
}
else
{
int index = k / fact[n - 1];
k = k % fact[n - 1];
if (k == 0)
index--;
val = nums.ToArray()[index];
}
str.Append(val);
nums.Remove(val);
Permutation(n - 1, k, nums, str);
}
static string GetPermutation( int n, int k)
{
SortedSet< int > nums = new SortedSet< int >();
for ( int i = 1; i <= n; i++)
nums.Add(i);
System.Text.StringBuilder str = new System.Text.StringBuilder();
Permutation(n, k, nums, str);
return str.ToString();
}
public static void Main( string [] args)
{
int n = 3, k = 4;
string kth_perm_seq = GetPermutation(n, k);
Console.WriteLine(kth_perm_seq);
}
}
|
Javascript
const fact = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880];
function permutation(n, k, nums, str) {
if (n === 0) {
return ;
}
let val;
if (k <= 1 || k <= fact[n - 1]) {
val = (k === 0) ? [...nums][nums.size - 1] : [...nums][0];
} else {
const index = Math.floor(k / fact[n - 1]);
k = k % fact[n - 1];
if (k === 0) {
val = [...nums][index - 1];
} else {
val = [...nums][index];
}
}
str.push(val);
nums. delete (val);
permutation(n - 1, k, nums, str);
}
function getPermutation(n, k) {
const nums = new Set();
for (let i = 1; i <= n; i++) {
nums.add(i);
}
const str = [];
permutation(n, k, nums, str);
return str.join( '' );
}
const n = 3, k = 4;
const kth_perm_seq = getPermutation(n, k);
console.log(kth_perm_seq);
|
Output:
231
Time Complexity : O(N) for generating all the permutations and traversals.
Auxiliary Space : O(N) for storing all permutation.
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
02 Oct, 2023
Like Article
Save Article