Lexicographically Kth-smallest string having ‘a’ X times and ‘b’ Y times
Last Updated :
08 Feb, 2023
Given three non-negative integers, X, Y, and K, the task is to find the Kth smallest lexicographical string having X occurrences of character ‘a’ and Y occurrences of character ‘b’.
Examples:
Input: X = 2, Y = 3, K = 3
Output: abbab
Explanation:
First lexicographical smallest string = “aabbb”.
Second lexicographical smallest string = “ababb”.
Third lexicographical smallest string = “abbab”.
Input: X = 4, Y = 3, K = 4
Output: aaabbba
Naive Approach: The simplest approach is to generate all distinct permutations of the string X occurrences of character ‘a’ and Y occurrences of character ‘b’. Then first, sort the output string array in lexicographical order and print the Kth index string.
Time complexity: O(N*N!), where N is (X + Y)
Auxiliary Space: O(N!)
Efficient Approach: This problem has Overlapping Subproblems property and Optimal Substructure property. So this problem can be solved using Dynamic Programming. Like other typical Dynamic Programming(DP) problems, recomputation of the same subproblems can be avoided by constructing a temporary array that stores the results of subproblems. Follow the steps below to solve this problem.
- Initialize a 2D array, dp[][] where dp[i][j] denotes the number of strings containing i number of a’s, and j number of b’s.
- Iterate in the range [0, X] using the variable i:
- Iterate in the range [0, Y] using the variable j:
- If i is greater than 0, then update dp[i][j] to dp[i][j] + dp[i-1][j].
- If j is greater than 0, then update dp[i][j] to dp[i][j] + dp[i][j-1].
- Now, recursively find the Kth lexicographical smallest string by calling the function kthString(int X, int Y, int K).
- Handle the base cases:
- If there are only ‘a’ characters present then return a string of all ‘a’ characters.
- If there are only ‘b’ characters present then return a string of all ‘b’ characters.
- If there are more than or equal to K strings that start with ‘a’, then return “a” + kthString(X-1, Y, K).
- Else the first character of the resultant string is ‘b’, return “b” + kthString(X, Y-1, K – dp[X-1][Y]).
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
const int MAX = 30;
void findNumString( int X, int Y, int dp[][MAX])
{
for ( int i = 0; i < MAX; i++) {
for ( int j = 0; j < MAX; j++) {
dp[i][j] = 0;
}
}
dp[0][0] = 1;
for ( int i = 0; i <= X; ++i) {
for ( int j = 0; j <= Y; ++j) {
if (i > 0) {
dp[i][j] += dp[i - 1][j];
}
if (j > 0) {
dp[i][j] += dp[i][j - 1];
}
}
}
}
string kthString( int X, int Y, int K, int dp[][MAX])
{
if (X == 0) {
return string(Y, 'b' );
}
if (Y == 0) {
return string(X, 'a' );
}
if (K <= dp[X - 1][Y]) {
return string( "a" ) + kthString(X - 1, Y, K, dp);
}
else {
return string( "b" )
+ kthString(X, Y - 1,
K - dp[X - 1][Y], dp);
}
}
void kthStringUtil( int X, int Y, int K)
{
int dp[MAX][MAX];
findNumString(X, Y, dp);
cout << kthString(X, Y, K, dp) << '\n' ;
}
int main()
{
int X = 4;
int Y = 3;
int K = 4;
kthStringUtil(X, Y, K);
return 0;
}
|
Java
public class GFG
{
static int MAX = 30 ;
static void findNumString( int X, int Y, int dp[][])
{
for ( int i = 0 ; i < MAX; i++) {
for ( int j = 0 ; j < MAX; j++) {
dp[i][j] = 0 ;
}
}
dp[ 0 ][ 0 ] = 1 ;
for ( int i = 0 ; i <= X; ++i) {
for ( int j = 0 ; j <= Y; ++j) {
if (i > 0 ) {
dp[i][j] += dp[i - 1 ][j];
}
if (j > 0 ) {
dp[i][j] += dp[i][j - 1 ];
}
}
}
}
static String kthString( int X, int Y, int K, int dp[][])
{
String x1 = "" ;
String y1 = "" ;
for ( int i= 0 ;i<Y;i++){
x1 += 'b' ;
}
for ( int i= 0 ;i<X;i++){
y1 += 'a' ;
}
if (X == 0 )
return x1;
if (Y == 0 )
return y1;
if (K <= dp[X - 1 ][Y]) {
return ( "a" + kthString(X - 1 , Y, K, dp));
}
else {
return ( "b" + kthString(X, Y - 1 , K - dp[X - 1 ][Y], dp));
}
}
static void kthStringUtil( int X, int Y, int K)
{
int dp[][] = new int [MAX][MAX];
findNumString(X, Y, dp);
System.out.println(kthString(X, Y, K, dp));
}
public static void main(String args[])
{
int X = 4 ;
int Y = 3 ;
int K = 4 ;
kthStringUtil(X, Y, K);
}
}
|
Python3
from typing import Mapping
MAX = 30
def findNumString(X, Y, dp):
for i in range ( 0 , MAX ):
for j in range ( 0 , MAX ):
dp[i][j] = 0
dp[ 0 ][ 0 ] = 1
for i in range ( 0 , X + 1 ):
for j in range ( 0 , Y + 1 ):
if (i > 0 ):
dp[i][j] + = dp[i - 1 ][j]
if (j > 0 ):
dp[i][j] + = dp[i][j - 1 ]
def kthString(X, Y, K, dp):
x1 = ""
y1 = ""
for i in range ( 0 , Y):
x1 + = 'b'
for i in range ( 0 , X):
y1 + = 'a'
if (X = = 0 ):
return x1
if (Y = = 0 ):
return y1
if (K < = dp[X - 1 ][Y]):
return "a" + kthString(X - 1 , Y, K, dp)
else :
return "b" + kthString(X, Y - 1 ,
K - dp[X - 1 ][Y], dp)
def kthStringUtil(X, Y, K):
dp = [[ 0 for i in range ( MAX )]
for col in range ( MAX )]
findNumString(X, Y, dp)
print (kthString(X, Y, K, dp))
X = 4
Y = 3
K = 4
kthStringUtil(X, Y, K)
|
C#
using System;
class GFG{
static int MAX = 30;
static void findNumString( int X, int Y, int [,] dp)
{
for ( int i = 0; i < MAX; i++) {
for ( int j = 0; j < MAX; j++) {
dp[i, j] = 0;
}
}
dp[0, 0] = 1;
for ( int i = 0; i <= X; ++i) {
for ( int j = 0; j <= Y; ++j) {
if (i > 0) {
dp[i, j] += dp[i - 1, j];
}
if (j > 0) {
dp[i, j] += dp[i, j - 1];
}
}
}
}
static string kthString( int X, int Y, int K, int [,] dp)
{
string x1 = "" ;
string y1 = "" ;
for ( int i=0;i<Y;i++){
x1 += 'b' ;
}
for ( int i=0;i<X;i++){
y1 += 'a' ;
}
if (X == 0)
return x1;
if (Y == 0)
return y1;
if (K <= dp[X - 1, Y]) {
return ( "a" + kthString(X - 1, Y, K, dp));
}
else {
return ( "b" + kthString(X, Y - 1, K - dp[X - 1, Y], dp));
}
}
static void kthStringUtil( int X, int Y, int K)
{
int [,] dp = new int [MAX, MAX];
findNumString(X, Y, dp);
Console.WriteLine(kthString(X, Y, K, dp));
}
static void Main()
{
int X = 4;
int Y = 3;
int K = 4;
kthStringUtil(X, Y, K);
}
}
|
Javascript
<script>
const MAX = 30
function findNumString(X, Y, dp){
for (let i = 0; i < MAX; i++)
for (let j = 0; j < MAX; j++)
dp[i][j] = 0
dp[0][0] = 1
for (let i = 0; i < X + 1; i++)
{
for (let j = 0; j < Y + 1; j++)
{
if (i > 0)
dp[i][j] += dp[i - 1][j]
if (j > 0)
dp[i][j] += dp[i][j - 1]
}
}
}
function kthString(X, Y, K, dp){
let x1 = ""
let y1 = ""
for (let i = 0; i < Y; i++)
x1 += 'b'
for (let i = 0; i < X; i++)
y1 += 'a'
if (X == 0)
return x1
if (Y == 0)
return y1
if (K <= dp[X - 1][Y])
return "a" + kthString(X - 1, Y, K, dp)
else
return "b" + kthString(X, Y - 1,
K - dp[X - 1][Y], dp)
}
function kthStringUtil(X, Y, K)
{
let dp = new Array(MAX);
for (let i = 0; i < MAX; i++)
{
dp[i] = new Array(MAX);
}
findNumString(X, Y, dp)
document.write(kthString(X, Y, K, dp), "</br>" )
}
let X = 4
let Y = 3
let K = 4
kthStringUtil(X, Y, K)
</script>
|
Time Complexity: O(X*Y)
Auxiliary Space: O(X*Y)
Efficient Approach: The above approach can further be optimized by iteratively implementing the KthString function. Follow the steps below to solve this problem:
- Declare a 2D array, dp where dp[i][j] denotes the number of strings containing i number of a’s, and j number of b’s.
- Iterate in the range [0, X] using the variable i:
- Iterate in the range [0, Y] using the variable j:
- If i is greater than 0, then update dp[i][j] to dp[i][j] + dp[i-1][j].
- If j is greater than 0, then update dp[i][j] to dp[i][j] + dp[i][j-1].
- Now, iteratively find the Kth lexicographical smallest string.
- Traverse while X is greater than 0 and Y is greater than 0:
- If there are more than or equal to K strings that start with ‘a’, then print ‘a’ and decrement X by 1.
- Else, the first character of the resultant string is ‘b’, print ‘b’, and decrement Y by 1.
- If there are only ‘a’ characters present then print a string of all ‘a‘ characters.
- If there are only ‘b‘ characters present then print a string of all ‘b‘ characters.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
const int MAX = 30;
void findNumString( int X, int Y, int dp[][MAX])
{
for ( int i = 0; i < MAX; i++) {
for ( int j = 0; j < MAX; j++) {
dp[i][j] = 0;
}
}
dp[0][0] = 1;
for ( int i = 0; i <= X; ++i) {
for ( int j = 0; j <= Y; ++j) {
if (i > 0) {
dp[i][j] += dp[i - 1][j];
}
if (j > 0) {
dp[i][j] += dp[i][j - 1];
}
}
}
}
void kthString( int X, int Y, int K, int dp[][MAX])
{
while (X > 0 and Y > 0) {
if (K <= dp[X - 1][Y]) {
cout << 'a' ;
X -= 1;
}
else {
K -= dp[X - 1][Y];
cout << 'b' ;
Y -= 1;
}
}
cout << string(X, 'a' );
cout << string(Y, 'b' );
cout << '\n' ;
}
void kthStringUtil( int X, int Y, int K)
{
int dp[MAX][MAX];
findNumString(X, Y, dp);
kthString(X, Y, K, dp);
}
int main()
{
int X = 4;
int Y = 3;
int K = 4;
kthStringUtil(X, Y, K);
return 0;
}
|
Java
import java.io.*;
class Main {
static final int MAX = 30 ;
static void findNumString( int X, int Y, int [][] dp) {
for ( int i = 0 ; i < MAX; i++) {
for ( int j = 0 ; j < MAX; j++) {
dp[i][j] = 0 ;
}
}
dp[ 0 ][ 0 ] = 1 ;
for ( int i = 0 ; i <= X; ++i) {
for ( int j = 0 ; j <= Y; ++j) {
if (i > 0 ) {
dp[i][j] += dp[i - 1 ][j];
}
if (j > 0 ) {
dp[i][j] += dp[i][j - 1 ];
}
}
}
}
static void kthString( int X, int Y, int K, int [][] dp) {
while (X > 0 && Y > 0 ) {
if (K <= dp[X - 1 ][Y]) {
System.out.print( "a" );
X -= 1 ;
}
else {
K -= dp[X - 1 ][Y];
System.out.print( "b" );
Y -= 1 ;
}
}
for ( int i = 0 ; i < X; i++) {
System.out.print( "a" );
}
for ( int i = 0 ; i < Y; i++) {
System.out.print( "b" );
}
System.out.println();
}
static void kthStringUtil( int X, int Y, int K) {
int [][] dp = new int [MAX][MAX];
findNumString(X, Y, dp);
kthString(X, Y, K, dp);
}
public static void main(String[] args) {
int X = 4 ;
int Y = 3 ;
int K = 4 ;
kthStringUtil(X, Y, K);
}
}
|
Python3
MAX = 30 ;
def find_num_string(X, Y, dp):
for i in range ( MAX ):
for j in range ( MAX ):
dp[i][j] = 0
dp[ 0 ][ 0 ] = 1
for i in range (X + 1 ):
for j in range (Y + 1 ):
if i > 0 :
dp[i][j] + = dp[i - 1 ][j]
if j > 0 :
dp[i][j] + = dp[i][j - 1 ]
def kth_string(X, Y, K, dp):
while X > 0 and Y > 0 :
if K < = dp[X - 1 ][Y]:
print ( 'a' , end = '')
X - = 1
else :
K - = dp[X - 1 ][Y]
print ( 'b' , end = '')
Y - = 1
print ( 'a' * X, end = '')
print ( 'b' * Y)
def kth_string_util(X, Y, K):
dp = [[ 0 for j in range ( MAX )] for i in range ( MAX )]
find_num_string(X, Y, dp)
kth_string(X, Y, K, dp)
if __name__ = = '__main__' :
X = 4
Y = 3
K = 4
kth_string_util(X, Y, K)
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int MAX = 30;
static void findNumString( int X, int Y, int [][] dp)
{
for ( int i = 0 ; i < MAX ; i++) {
for ( int j = 0 ; j < MAX ; j++) {
dp[i][j] = 0;
}
}
dp[0][0] = 1;
for ( int i = 0 ; i <= X ; ++i) {
for ( int j = 0 ; j <= Y ; ++j) {
if (i > 0) {
dp[i][j] += dp[i - 1][j];
}
if (j > 0) {
dp[i][j] += dp[i][j - 1];
}
}
}
}
static void kthString( int X, int Y, int K, int [][] dp)
{
while (X > 0 && Y > 0) {
if (K <= dp[X - 1][Y]) {
Console.Write( 'a' );
X -= 1;
}
else {
K -= dp[X - 1][Y];
Console.Write( 'b' );
Y -= 1;
}
}
String ans = "" ;
for ( int i = 0 ; i < X ; i++){
ans+= "a" ;
}
Console.Write(ans);
ans = "" ;
for ( int i = 0 ; i < Y ; i++){
ans+= "b" ;
}
Console.Write(ans);
Console.Write( "\n" );
}
static void kthStringUtil( int X, int Y, int K)
{
int [][] dp = new int [MAX][];
for ( int i = 0 ; i < MAX ; i++){
dp[i] = new int [MAX];
}
findNumString(X, Y, dp);
kthString(X, Y, K, dp);
}
public static void Main( string [] args){
int X = 4;
int Y = 3;
int K = 4;
kthStringUtil(X, Y, K);
}
}
|
Javascript
const MAX = 30;
function findNumString( X, Y, dp)
{
for (let i = 0; i < MAX; i++) {
for (let j = 0; j < MAX; j++) {
dp[i][j] = 0;
}
}
dp[0][0] = 1;
for (let i = 0; i <= X; ++i) {
for (let j = 0; j <= Y; ++j) {
if (i > 0) {
dp[i][j] += dp[i - 1][j];
}
if (j > 0) {
dp[i][j] += dp[i][j - 1];
}
}
}
}
function kthString( X, Y, K, dp)
{
while (X > 0 && Y > 0) {
if (K <= dp[X - 1][Y]) {
document.write( 'a' );
X -= 1;
}
else {
K -= dp[X - 1][Y];
document.write( 'b' );
Y -= 1;
}
}
let ans = "" ;
for (let i = 0 ; i < X ; i++){
ans+= "a" ;
}
document.write(ans);
ans = "" ;
for (let i = 0 ; i < Y ; i++){
ans+= "b" ;
}
document.write(ans);
}
function kthStringUtil( X, Y, K)
{
let dp= new Array(MAX);
for (let i=0; i<MAX; i++)
dp[i]= new Array(MAX);
findNumString(X, Y, dp);
kthString(X, Y, K, dp);
}
let X = 4;
let Y = 3;
let K = 4;
kthStringUtil(X, Y, K);
|
Time Complexity: O(X*Y)
Auxiliary Space: O(X*Y)
Share your thoughts in the comments
Please Login to comment...