给定三个非负整数X 、 Y和K , 任务是找到字符的第K个具有最小辞书字符串X出现“a”和字符Y的出现“B”。
例子:
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
原始的方法:最简单的方法是生成字符串X字符出现的“A”和字符Y的出现“B”的所有不同的排列组合。然后首先按字典顺序对输出字符串数组进行排序并打印第K 个索引字符串。
时间复杂度: O(N*N!),其中 N 是 (X + Y)
辅助空间: O(N!)
高效方法:这个问题具有重叠子问题属性和最优子结构属性。所以这个问题可以用动态规划解决。与其他典型的动态规划 (DP) 问题一样,可以通过构造一个存储子问题结果的临时数组来避免对相同子问题的重新计算。请按照以下步骤解决此问题。
- 初始化一个二维数组, dp[][] ,其中dp[i][j]表示包含i个a和j个b 的字符串的数量。
- 使用变量i在范围[0, X] 中迭代:
- 使用变量j在范围[0, Y] 中迭代:
- 如果i大于0,则将dp[i][j]更新为dp[i][j] + dp[i-1][j] 。
- 如果j大于0 ,则将dp[i][j]更新为dp[i][j] + dp[i][j-1] 。
- 使用变量j在范围[0, Y] 中迭代:
- 现在,通过调用函数kthString(int X, int Y, int K)递归地找到第K 个字典序最小的字符串。
- 处理基本情况:
- 如果只存在‘a’ 个字符,则返回一个包含所有‘a’ 个字符的字符串。
- 如果只存在‘b’ 个字符,则返回一个包含所有‘b’ 个字符的字符串。
- 如果有大于或等于K 个以‘a’开头的字符串,则返回“a” + kthString(X-1, Y, K) 。
- 否则结果字符串的第一个字符是‘b’ ,返回“b” + kthString(X, Y-1, K – dp[X-1][Y]) 。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
const int MAX = 30;
// Function to fill dp array
void findNumString(int X, int Y, int dp[][MAX])
{
// Initialize all the entries with 0
for (int i = 0; i < MAX; i++) {
for (int j = 0; j < MAX; j++) {
dp[i][j] = 0;
}
}
// Update dp[0][0] to 1
dp[0][0] = 1;
// Traverse the dp array
for (int i = 0; i <= X; ++i) {
for (int j = 0; j <= Y; ++j) {
// Update the value of dp[i][j]
if (i > 0) {
dp[i][j] += dp[i - 1][j];
}
if (j > 0) {
dp[i][j] += dp[i][j - 1];
}
}
}
}
// Recursive function to find the Kth
// lexicographical smallest string
string kthString(int X, int Y, int K, int dp[][MAX])
{
// Handle the base cases
if (X == 0) {
return string(Y, 'b');
}
if (Y == 0) {
return string(X, 'a');
}
// If there are more than or equal
// to K strings which start with a,
// then the first character is 'a'
if (K <= dp[X - 1][Y]) {
return string("a") + kthString(X - 1, Y, K, dp);
}
// Otherwise the first character
// of the resultant string is 'b'
else {
return string("b")
+ kthString(X, Y - 1,
K - dp[X - 1][Y], dp);
}
}
// Function to find the Kth
// lexicographical smallest string
void kthStringUtil(int X, int Y, int K)
{
int dp[MAX][MAX];
// Function call to fill the dp array
findNumString(X, Y, dp);
// Print the resultant string
cout << kthString(X, Y, K, dp) << '\n';
}
// Driver Code
int main()
{
// Given Input
int X = 4;
int Y = 3;
int K = 4;
// Function Call
kthStringUtil(X, Y, K);
return 0;
}
Java
// Java program for the above approach
public class GFG
{
static int MAX = 30;
// Function to fill dp array
static void findNumString(int X, int Y, int dp[][])
{
// Initialize all the entries with 0
for (int i = 0; i < MAX; i++) {
for (int j = 0; j < MAX; j++) {
dp[i][j] = 0;
}
}
// Update dp[0][0] to 1
dp[0][0] = 1;
// Traverse the dp array
for (int i = 0; i <= X; ++i) {
for (int j = 0; j <= Y; ++j) {
// Update the value of dp[i][j]
if (i > 0) {
dp[i][j] += dp[i - 1][j];
}
if (j > 0) {
dp[i][j] += dp[i][j - 1];
}
}
}
}
// Recursive function to find the Kth
// lexicographical smallest string
static String kthString(int X, int Y, int K, int dp[][])
{
// Handle the base cases
String x1 = "";
String y1 = "";
for (int i=0;i
Python3
# Python3 program for the above approach
from typing import Mapping
MAX = 30
# Function to fill dp array
def findNumString(X, Y, dp):
# Initialize all the entries with 0
for i in range(0, MAX):
for j in range(0, MAX):
dp[i][j] = 0
# Update dp[0][0] to 1
dp[0][0] = 1
# Traverse the dp array
for i in range(0, X + 1):
for j in range(0, Y + 1):
# Update the value of dp[i][j]
if (i > 0):
dp[i][j] += dp[i - 1][j]
if (j > 0):
dp[i][j] += dp[i][j - 1]
# Recursive function to find the Kth
# lexicographical smallest string
def kthString(X, Y, K, dp):
# Handle the base cases
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 there are more than or equal
# to K strings which start with a,
# then the first character is 'a'
if (K <= dp[X - 1][Y]):
return "a" + kthString(X - 1, Y, K, dp)
# Otherwise the first character
# of the resultant string is 'b'
else:
return "b" + kthString(X, Y - 1,
K - dp[X - 1][Y], dp)
# Function to find the Kth
# lexicographical smallest string
def kthStringUtil(X, Y, K):
dp = [[0 for i in range(MAX)]
for col in range(MAX)]
# Function call to fill the dp array
findNumString(X, Y, dp)
# Print the resultant
print(kthString(X, Y, K, dp))
# Driver Code
# Given Input
X = 4
Y = 3
K = 4
# Function Call
kthStringUtil(X, Y, K)
# This code is contributed by amreshkumar3
C#
// C# program for the above approach
using System;
class GFG{
static int MAX = 30;
// Function to fill dp array
static void findNumString(int X, int Y, int[,] dp)
{
// Initialize all the entries with 0
for (int i = 0; i < MAX; i++) {
for (int j = 0; j < MAX; j++) {
dp[i, j] = 0;
}
}
// Update dp[0][0] to 1
dp[0, 0] = 1;
// Traverse the dp array
for (int i = 0; i <= X; ++i) {
for (int j = 0; j <= Y; ++j) {
// Update the value of dp[i][j]
if (i > 0) {
dp[i, j] += dp[i - 1, j];
}
if (j > 0) {
dp[i, j] += dp[i, j - 1];
}
}
}
}
// Recursive function to find the Kth
// lexicographical smallest string
static string kthString(int X, int Y, int K, int[,] dp)
{
// Handle the base cases
string x1 = "";
string y1 = "";
for (int i=0;i
C++
// C++ program for the above approach
#include
using namespace std;
const int MAX = 30;
// Function to fill dp array
void findNumString(int X, int Y, int dp[][MAX])
{
// Initialize all the entries with 0
for (int i = 0; i < MAX; i++) {
for (int j = 0; j < MAX; j++) {
dp[i][j] = 0;
}
}
// Update dp[0][0] to 1
dp[0][0] = 1;
// Traverse the dp array
for (int i = 0; i <= X; ++i) {
for (int j = 0; j <= Y; ++j) {
// Update the value of dp[i][j]
if (i > 0) {
dp[i][j] += dp[i - 1][j];
}
if (j > 0) {
dp[i][j] += dp[i][j - 1];
}
}
}
}
// Iterative function to find the Kth
// lexicographical smallest string
void kthString(int X, int Y, int K, int dp[][MAX])
{
while (X > 0 and Y > 0) {
// If there are more than or
// equal to K strings which start
// with a, then print 'a'
if (K <= dp[X - 1][Y]) {
cout << 'a';
X -= 1;
}
// Otherwise the first character
// of the resultant string is b
else {
K -= dp[X - 1][Y];
cout << 'b';
Y -= 1;
}
}
// If there are only 'a' characters
// present then print a string of
// all 'a' characters
cout << string(X, 'a');
// If there are only 'b' characters
// present then print a string of
// all 'b' characters
cout << string(Y, 'b');
cout << '\n';
}
// Function to find the Kth
// lexicographical smallest string
void kthStringUtil(int X, int Y, int K)
{
int dp[MAX][MAX];
// Function call to fill the dp array
findNumString(X, Y, dp);
// Function call to find the
// required string
kthString(X, Y, K, dp);
}
// Driver Code
int main()
{
// Given Input
int X = 4;
int Y = 3;
int K = 4;
// Function Call
kthStringUtil(X, Y, K);
return 0;
}
aaabbba
时间复杂度: O(X*Y)
辅助空间: O(X*Y)
高效的方法:通过迭代实现KthString函数,可以进一步优化上述方法。请按照以下步骤解决此问题:
- 声明一个二维数组dp ,其中dp[i][j]表示包含i个a和j个b 的字符串的数量。
- 使用变量i在范围[0, X] 中迭代:
- 使用变量j在范围[0, Y] 中迭代:
- 如果i大于0,则将dp[i][j]更新为dp[i][j] + dp[i-1][j]。
- 如果j大于0 ,则将dp[i][j]更新为dp[i][j] + dp[i][j-1]。
- 使用变量j在范围[0, Y] 中迭代:
- 现在,迭代地找到第K 个字典序最小的字符串。
- 当X大于0且Y大于0 时遍历:
- 如果有大于或等于K 个以‘a’开头的字符串,则 打印‘a’并将X减1 。
- 否则,结果字符串的第一个字符是‘b’ ,打印‘b’ ,并将Y减1 。
- 如果只存在 ‘ a’字符,则打印所有 ‘ a ‘字符的字符串。
- 如果只存在 ‘ b ‘字符,则打印所有 ‘ b ‘字符的字符串。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
const int MAX = 30;
// Function to fill dp array
void findNumString(int X, int Y, int dp[][MAX])
{
// Initialize all the entries with 0
for (int i = 0; i < MAX; i++) {
for (int j = 0; j < MAX; j++) {
dp[i][j] = 0;
}
}
// Update dp[0][0] to 1
dp[0][0] = 1;
// Traverse the dp array
for (int i = 0; i <= X; ++i) {
for (int j = 0; j <= Y; ++j) {
// Update the value of dp[i][j]
if (i > 0) {
dp[i][j] += dp[i - 1][j];
}
if (j > 0) {
dp[i][j] += dp[i][j - 1];
}
}
}
}
// Iterative function to find the Kth
// lexicographical smallest string
void kthString(int X, int Y, int K, int dp[][MAX])
{
while (X > 0 and Y > 0) {
// If there are more than or
// equal to K strings which start
// with a, then print 'a'
if (K <= dp[X - 1][Y]) {
cout << 'a';
X -= 1;
}
// Otherwise the first character
// of the resultant string is b
else {
K -= dp[X - 1][Y];
cout << 'b';
Y -= 1;
}
}
// If there are only 'a' characters
// present then print a string of
// all 'a' characters
cout << string(X, 'a');
// If there are only 'b' characters
// present then print a string of
// all 'b' characters
cout << string(Y, 'b');
cout << '\n';
}
// Function to find the Kth
// lexicographical smallest string
void kthStringUtil(int X, int Y, int K)
{
int dp[MAX][MAX];
// Function call to fill the dp array
findNumString(X, Y, dp);
// Function call to find the
// required string
kthString(X, Y, K, dp);
}
// Driver Code
int main()
{
// Given Input
int X = 4;
int Y = 3;
int K = 4;
// Function Call
kthStringUtil(X, Y, K);
return 0;
}
aaabbba
时间复杂度: O(X*Y)
辅助空间: O(X*Y)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。