用最少的替换将字符串X 转换为字符串Y 的字谜
给定两个字符串X 和 Y,我们需要将字符串X 转换为字符串Y 的变位词,且替换次数最少。如果我们有多种实现目标的方法,我们会选择按字典顺序较小的字符串,其中每个字符串的长度
例子:
Input : X = "CDBABC"
Y = "ADCABD"
Output : Anagram : ADBADC
Number of changes made: 2
Input : X = "PJPOJOVMAK"
Y = "FVACRHLDAP"
Output : Anagram : ACPDFHVLAR
Number of changes made: 7
使用的方法:
我们必须将字符串X 转换为字符串Y 的字典序上最小的字谜,在原始字符串X 中进行最少的替换。我们维护两个计数器数组,用于存储两个字符串中每个字符的计数/频率。设两个字符串的计数器为和 .现在,根据定义,字谜意味着两个字谜中字符的频率始终相等。因此,要将字符串X 转换为字符串Y 的字谜,字符的频率应该相等。因此,为了将字符串X 转换为字符串Y 的变位词,我们总共需要进行的更改总数为
,我们迭代每个字符i 。
一半的工作已经完成,因为我们知道要完成多少次替换。我们现在需要字典上更小的字符串。现在,对于特定位置,我们查找从“A”到“Z”的所有可能字符,并检查每个字符是否适合该位置或现在。为了更好地理解,我们对字符串中的每个位置进行迭代。检查是否有一个字符存在于字符串Y 中而不存在于字符串X 中(或者字符的频率在字符串Y 中更多而在字符串X 中更少)。现在,如果有,我们检查X中当前位置的字符,是不是没有必要?即它在字符串X 中的频率是否更高而在字符串Y 中的频率更低。现在,如果所有的框都被打勾,我们进一步检查我们是否在这个位置插入了字符,因为我们需要生成字典上更小的字符串。如果所有条件都为真,我们将字符串X 中的字符替换为字符串Y 中的字符。在所有这些替换之后,我们可以打印更改后的字符串X 作为输出。
C++
// C++ program to convert string X to
// string Y which minimum number of changes.
#include
using namespace std;
#define MAX 26
// Function that converts string X
// into lexicographically smallest
// anagram of string Y with minimal changes
void printAnagramAndChanges(string X, string Y)
{
int countx[MAX] = {0}, county[MAX] = {0},
ctrx[MAX] = {0}, ctry[MAX] = {0};
int change = 0;
int l = X.length();
// Counting frequency of characters
// in each string.
for (int i = 0; i < l; i++) {
countx[X[i] - 'A']++;
county[Y[i] - 'A']++;
}
// We maintain two more counter arrays
// ctrx[] and ctry[]
// Ctrx[] maintains the count of extra
// elements present in string X than
// string Y
// Ctry[] maintains the count of
// characters missing from string X
// which should be present in string Y.
for (int i = 0; i < MAX; i++) {
if (countx[i] > county[i])
ctrx[i] += (countx[i] - county[i]);
else if (countx[i] < county[i])
ctry[i] += (county[i] - countx[i]);
change += abs(county[i] - countx[i]);
}
for (int i = 0; i < l; i++) {
// This means that we cannot edit the
// current character as it's frequency
// in string X is equal to or less
// than the frequency in string Y.
// Thus, we go to the next position
if (ctrx[X[i] - 'A'] == 0)
continue;
// Here, we try to find that character,
// which has more frequency in string Y
// and less in string X. We try to find
// this character in lexicographical
// order so that we get
// lexicographically smaller string
int j;
for (j = 0; j < MAX; j++)
if ((ctry[j]) > 0)
break;
// This portion deals with the
// lexicographical property.
// Now, we put a character in string X
// when either this character has smaller
// value than the character present there
// right now or if this is the last position
// for it to exchange, else we fix the
// character already present here in
// this position.
if (countx[X[i] - 'A'] == ctrx[X[i] - 'A']
|| X[i] - 'A' > j) {
countx[X[i] - 'A']--;
ctrx[X[i] - 'A']--;
ctry[j]--;
X[i] = 'A' + j;
}
else
countx[X[i] - 'A']--;
}
cout << "Anagram : " << X << endl;
cout << "Number of changes made : " << change / 2;
}
// Driver program
int main()
{
string x = "CDBABC", y = "ADCABD";
printAnagramAndChanges(x, y);
return 0;
}
Java
// Java program to convert string X to
// string Y which minimum number of changes.
class GFG
{
static final int MAX = 26;
// Function that converts string X
// into lexicographically smallest
// anagram of string Y with minimal changes
static void printAnagramAndChanges(char[] X,
char[] Y)
{
int countx[] = new int[MAX], county[] = new int[MAX],
ctrx[] = new int[MAX], ctry[] = new int[MAX];
int change = 0;
int l = X.length;
// Counting frequency of characters
// in each string.
for (int i = 0; i < l; i++)
{
countx[X[i] - 'A']++;
county[Y[i] - 'A']++;
}
// We maintain two more counter arrays
// ctrx[] and ctry[]
// Ctrx[] maintains the count of extra
// elements present in string X than
// string Y
// Ctry[] maintains the count of
// characters missing from string X
// which should be present in string Y.
for (int i = 0; i < MAX; i++)
{
if (countx[i] > county[i])
{
ctrx[i] += (countx[i] - county[i]);
}
else if (countx[i] < county[i])
{
ctry[i] += (county[i] - countx[i]);
}
change += Math.abs(county[i] - countx[i]);
}
for (int i = 0; i < l; i++)
{
// This means that we cannot edit the
// current character as it's frequency
// in string X is equal to or less
// than the frequency in string Y.
// Thus, we go to the next position
if (ctrx[X[i] - 'A'] == 0)
{
continue;
}
// Here, we try to find that character,
// which has more frequency in string Y
// and less in string X. We try to find
// this character in lexicographical
// order so that we get
// lexicographically smaller string
int j;
for (j = 0; j < MAX; j++)
{
if ((ctry[j]) > 0)
{
break;
}
}
// This portion deals with the
// lexicographical property.
// Now, we put a character in string X
// when either this character has smaller
// value than the character present there
// right now or if this is the last position
// for it to exchange, else we fix the
// character already present here in
// this position.
if (countx[X[i] - 'A'] == ctrx[X[i] - 'A']
|| X[i] - 'A' > j)
{
countx[X[i] - 'A']--;
ctrx[X[i] - 'A']--;
ctry[j]--;
X[i] = (char) ('A' + j);
}
else
{
countx[X[i] - 'A']--;
}
}
System.out.println("Anagram : " + String.valueOf(X));
System.out.println("Number of changes made : " + change / 2);
}
// Driver code
public static void main(String[] args)
{
String x = "CDBABC", y = "ADCABD";
printAnagramAndChanges(x.toCharArray(), y.toCharArray());
}
}
// This code is contributed by Rajput-Ji
Python3
# Python3 program to convert string X to
# string Y which minimum number of changes.
MAX = 26
# Function that converts string X
# into lexicographically smallest
# anagram of string Y with minimal changes
def printAnagramAndChanges(x, y):
x = list(x)
y = list(y)
countx, county = [0] * MAX, [0] * MAX
ctrx, ctry = [0] * MAX, [0] * MAX
change = 0
l = len(x)
# Counting frequency of characters
# in each string.
for i in range(l):
countx[ord(x[i]) - ord('A')] += 1
county[ord(y[i]) - ord('A')] += 1
# We maintain two more counter arrays
# ctrx[] and ctry[]
# Ctrx[] maintains the count of extra
# elements present in string X than
# string Y
# Ctry[] maintains the count of
# characters missing from string X
# which should be present in string Y.
for i in range(MAX):
if countx[i] > county[i]:
ctrx[i] += (countx[i] - county[i])
elif countx[i] < county[i]:
ctry[i] += (county[i] - countx[i])
change += abs(county[i] - countx[i])
for i in range(l):
# This means that we cannot edit the
# current character as it's frequency
# in string X is equal to or less
# than the frequency in string Y.
# Thus, we go to the next position
if ctrx[ord(x[i]) - ord('A')] == 0:
continue
# Here, we try to find that character,
# which has more frequency in string Y
# and less in string X. We try to find
# this character in lexicographical
# order so that we get
# lexicographically smaller string
j = 0
for j in range(MAX):
if ctry[j] > 0:
break
# This portion deals with the
# lexicographical property.
# Now, we put a character in string X
# when either this character has smaller
# value than the character present there
# right now or if this is the last position
# for it to exchange, else we fix the
# character already present here in
# this position.
if countx[ord(x[i]) -
ord('A')] == ctrx[ord(x[i]) - ord('A')] or \
ord(x[i]) - ord('A') > j:
countx[ord(x[i]) - ord('A')] -= 1
ctrx[ord(x[i]) - ord('A')] -= 1
ctry[j] -= 1
x[i] = chr(ord('A') + j)
else:
countx[ord(x[i]) - ord('A')] -= 1
print("Anagram :", ''.join(x))
print("Number of changes made :", change // 2)
# Driver Code
if __name__ == "__main__":
x = "CDBABC"
y = "ADCABD"
printAnagramAndChanges(x, y)
# This code is contributed by
# sanjeev2552
C#
// C# program to convert string X to
// string Y which minimum number of changes.
using System;
class GFG
{
static readonly int MAX = 26;
// Function that converts string X
// into lexicographically smallest
// anagram of string Y with minimal changes
static void printAnagramAndChanges(char[] X,
char[] Y)
{
int []countx = new int[MAX];
int []county = new int[MAX];
int []ctrx = new int[MAX];
int []ctry = new int[MAX];
int change = 0;
int l = X.Length;
// Counting frequency of characters
// in each string.
for (int i = 0; i < l; i++)
{
countx[X[i] - 'A']++;
county[Y[i] - 'A']++;
}
// We maintain two more counter arrays
// ctrx[] and ctry[]
// Ctrx[] maintains the count of extra
// elements present in string X than
// string Y
// Ctry[] maintains the count of
// characters missing from string X
// which should be present in string Y.
for (int i = 0; i < MAX; i++)
{
if (countx[i] > county[i])
{
ctrx[i] += (countx[i] - county[i]);
}
else if (countx[i] < county[i])
{
ctry[i] += (county[i] - countx[i]);
}
change += Math.Abs(county[i] - countx[i]);
}
for (int i = 0; i < l; i++)
{
// This means that we cannot edit the
// current character as it's frequency
// in string X is equal to or less
// than the frequency in string Y.
// Thus, we go to the next position
if (ctrx[X[i] - 'A'] == 0)
{
continue;
}
// Here, we try to find that character,
// which has more frequency in string Y
// and less in string X. We try to find
// this character in lexicographical
// order so that we get
// lexicographically smaller string
int j;
for (j = 0; j < MAX; j++)
{
if ((ctry[j]) > 0)
{
break;
}
}
// This portion deals with the
// lexicographical property.
// Now, we put a character in string X
// when either this character has smaller
// value than the character present there
// right now or if this is the last position
// for it to exchange, else we fix the
// character already present here in
// this position.
if (countx[X[i] - 'A'] == ctrx[X[i] - 'A']
|| X[i] - 'A' > j)
{
countx[X[i] - 'A']--;
ctrx[X[i] - 'A']--;
ctry[j]--;
X[i] = (char) ('A' + j);
}
else
{
countx[X[i] - 'A']--;
}
}
Console.WriteLine("Anagram : " +
String.Join("",X));
Console.WriteLine("Number of changes made : " +
change / 2);
}
// Driver code
public static void Main(String[] args)
{
String x = "CDBABC", y = "ADCABD";
printAnagramAndChanges(x.ToCharArray(),
y.ToCharArray());
}
}
// This code is contributed by 29AjayKumar
Javascript
输出:
Anagram : ADBADC
Number of changes made : 2
总时间复杂度为当我们忽略常量时,复杂度是