给定长度为N的小写字母组成的字符串S ,任务是计算为使给定字符串S特殊而需要替换的最小字符数。
A string S is special if and only if for all possible pairs (S[i], S[j]) ( 1-based indexing ) where 1 ≤ i ≤ N/2 and N / 2 + 1 ≤ j ≤ N, one of the following condition must be true:
- S[i] < S[j]: For indices (i, j), each character in the left half (S[i]) is less than each character in the right half (S[j]).
- S[i] > S[j]: For index (i, j), each character in left half (S[i]) is greater than each character in the right half (S[j]).
- S[i] = S[j]: For index (i, j), each character in left half (S[i]) is equal to each character in the right half (S[j]).
例子:
Input: S = “aababc“
Output: 2
Explanation:
The left and right part of the string are Left= “aab”, Right=”abc”
Operation 1: Change s[4] → d
Operation 2: Change s[5] → d
After applying the above changes, the resultant string is “aabddc” which satisfy all the conditions for special string.
Input: S = “aabaab”
Output: 2
Explanation:
The left and right part of the string are Left=”aab” Right=”aab”
Operation 1: Change s[3] → a
Operation 2: Change s[6] → a
After applying the above changes, the resultant string is “aaaaaa” which satisfy all the conditions for special string.
方法:想法是观察到,通过计算字符的频率可以完成s [i] == s [j]的26个字母的更改。请按照以下步骤解决以上问题:
- 存储左和右一半的字符的频率分别向右[]数组中存储的左[]和。
- 初始化变量计数以跟踪要进行的最少更改。
- 使用变量d遍历[0,26]范围,并根据以下情况更改字符:
- 对于s [i]等于s [j]:使所有字符等于字符c,则count的值为(N –左–右) 。
- 对于s [i]小于s [j]:
- 最初,在最大更改数的情况下,在左侧进行更改,使更改为N / 2 。
- 减去左侧它们≤d找到剩余的字符改变所有字符。
- 添加在右侧其是等于d改变那些比d为变化更大的字符中的所有字符– =左和变化+ =右。
- 对于s [i]大于s [j]:
- 最初,在最大更改数量的情况下,在右侧进行更改,使更改为N / 2 。
- 减去右侧被≤d找到剩余的字符改变所有字符。
- 在左侧添加等于d的所有字符,以将这些字符更改为> d。 (s [i]
change + = left和change-= right 。
- 在上述情况下,所有计数的最小值是必需的结果。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function that finds the minimum
// count of steps required to make
// the string special
int minChange(string s, int n)
{
// Stores the frequency of the
// left & right half of string
int L[26] = {0};
int R[26] = {0};
// Find frequency of left half
for(int i = 0; i < n / 2; i++)
{
char ch = s[i];
L[ch - 'a']++;
}
// Find frequency of left half
for(int i = n / 2; i < n; i++)
{
char ch = s[i];
R[ch - 'a']++;
}
int count = n;
// Make all characters equal
// to character c
for(char ch = 'a'; ch <= 'z'; ch++)
{
count = min(count,
n - L[ch - 'a'] -
R[ch - 'a']);
}
// Case 1: For s[i] < s[j]
int change = n / 2;
for(int d = 0; d + 1 < 26; d++)
{
// Subtract all the characters
// on left side that are <=d
change -= L[d];
// Adding all characters on the
// right side that same as d
change += R[d];
// Find minimum value of count
count = min(count, change);
}
// Similarly for Case 2: s[i] > s[j]
change = n / 2;
for(int d = 0; d + 1 < 26; d++)
{
change -= R[d];
change += L[d];
count = min(change, count);
}
// Return the minimum changes
return count;
}
// Driver Code
int main()
{
// Given string S
string S = "aababc";
int N = S.length();
// Function Call
cout << minChange(S, N) << "\n";
}
// This code is contributed by sallagondaavinashreddy7
Java
// Java program for the above approach
import java.io.*;
import java.util.*;
class Main {
// Function that finds the minimum
// count of steps required to make
// the string special
public static int minChange(String s,
int n)
{
// Stores the frequency of the
// left & right half of string
int L[] = new int[26];
int R[] = new int[26];
// Find frequency of left half
for (int i = 0; i < n / 2; i++) {
char ch = s.charAt(i);
L[ch - 'a']++;
}
// Find frequency of left half
for (int i = n / 2; i < n; i++) {
char ch = s.charAt(i);
R[ch - 'a']++;
}
int count = n;
// Make all characters equal
// to character c
for (char ch = 'a'; ch <= 'z'; ch++) {
count = Math.min(
count,
n - L[ch - 'a']
- R[ch - 'a']);
}
// Case 1: For s[i] < s[j]
int change = n / 2;
for (int d = 0; d + 1 < 26; d++) {
// Subtract all the characters
// on left side that are <=d
change -= L[d];
// Adding all characters on the
// right side that same as d
change += R[d];
// Find minimum value of count
count = Math.min(count, change);
}
// Similarly for Case 2: s[i] > s[j]
change = n / 2;
for (int d = 0; d + 1 < 26; d++) {
change -= R[d];
change += L[d];
count = Math.min(change, count);
}
// Return the minimum changes
return count;
}
// Driver Code
public static void main(String[] args)
{
// Given string S
String S = "aababc";
int N = S.length();
// Function Call
System.out.println(minChange(S, N));
}
}
Python3
# Python3 program for the
# above approach
# Function that finds the minimum
# count of steps required to make
# the string special
def minChange (s, n):
# Stores the frequency of the
# left & right half of string
L = [0] * 26;
R = [0] * 26;
# Find frequency of left half
for i in range(0, n // 2):
ch = s[i];
L[ord(ch) -
ord('a')] += 1;
# Find frequency of left half
for i in range(n // 2, n):
ch = s[i];
R[ord(ch) -
ord('a')] += 1;
count = n;
# Make all characters equal
# to character c
for ch in range(ord('a'),
ord('z')):
count = min(count, n - L[ch - ord('a')] -
R[ch - ord('a')]);
# Case 1: For s[i] < s[j]
change = n / 2;
for d in range(0, 25):
# Subtract all the characters
# on left side that are <=d
change -= L[d];
# Adding all characters on the
# right side that same as d
change += R[d];
# Find minimum value of count
count = min(count, change);
# Similarly for Case 2: s[i] > s[j]
change = n / 2;
for d in range(0, 25):
change -= R[d];
change += L[d];
count = min(change, count);
# Return the minimum changes
return int(count);
# Driver Code
if __name__ == '__main__':
# Given string S
S = "aababc";
N = len(S);
# Function Call
print(minChange(S, N));
# This code is contributed by shikhasingrajput
C#
// C# program for the above approach
using System;
class GFG{
// Function that finds the minimum
// count of steps required to make
// the string special
public static int minChange(String s,
int n)
{
// Stores the frequency of the
// left & right half of string
int []L = new int[26];
int []R = new int[26];
// Find frequency of left half
for(int i = 0; i < n / 2; i++)
{
char ch = s[i];
L[ch - 'a']++;
}
// Find frequency of left half
for(int i = n / 2; i < n; i++)
{
char ch = s[i];
R[ch - 'a']++;
}
int count = n;
// Make all characters equal
// to character c
for(char ch = 'a'; ch <= 'z'; ch++)
{
count = Math.Min(count,
n - L[ch - 'a'] -
R[ch - 'a']);
}
// Case 1: For s[i] < s[j]
int change = n / 2;
for(int d = 0; d + 1 < 26; d++)
{
// Subtract all the characters
// on left side that are <=d
change -= L[d];
// Adding all characters on the
// right side that same as d
change += R[d];
// Find minimum value of count
count = Math.Min(count, change);
}
// Similarly for Case 2: s[i] > s[j]
change = n / 2;
for(int d = 0; d + 1 < 26; d++)
{
change -= R[d];
change += L[d];
count = Math.Min(change, count);
}
// Return the minimum changes
return count;
}
// Driver Code
public static void Main(String[] args)
{
// Given string S
String S = "aababc";
int N = S.Length;
// Function Call
Console.WriteLine(minChange(S, N));
}
}
// This code is contributed by Amit Katiyar
2
时间复杂度: O(N)
辅助空间: O(1)