题意:
给定字母组成的字符串, 将其变为前段大写, 后段小写的形式.
每次操作可改变一个字母的大小写, 求最小操作数
思路:
-
求最小操作数, 即为选定一个最合适的位置, 在此之前的大写字母变小写, 之后的小写字母变大写, 该位置本身的字母是大写还是小写无关紧要(除了首尾两位). 而这些要更改字母的总数就是该位置的操作数了.
-
使用前缀和求得每个位置前大写个数, 后缀和求得每个位置后小写个数,计算的复杂度为O(n)
-
再遍历一下, 求得最小值, 输出
注意点:
题目要求全大写或全小写不符合要求.
所以最佳位置不能选在第一个和最后一个(这些位置上字母的大小写不可忽略, 头必须大写, 尾必须小写. 不符合的话需要被改掉, 而最佳位置的字母不会被更改)
错误原因:
根本没想到用前缀和...
一直在想能不能用递归求解, 把题目想复杂了, 看了题解直呼原来如此!
输入:
一个字符串
输出:
一个整数,表示最少的操作次数。
AC代码:
#include <string>
using namespace std;
int fron[100005] = {0, 0}, back[100005] = {0, 0};
string str;
bool islower(char s)
{
return s <= 'z' && s >= 'a';
}
bool isupper(char s)
{
return s <= 'Z' && s >= 'A';
}
int main()
{
cin >> str;//输入
int length = str.size();
fron[0] = 0;
back[length - 1] = 0;
for (int i = 1, j = length - 2; i < length - 1, j > 0; i++, j--)
{//双指针分别从后面和前面开始计算字母总数, 并存到数组中
if (islower(str[i - 1]))
fron[i] = fron[i - 1] + 1;
else
fron[i] = fron[i - 1];
if (isupper(str[j + 1]))
back[j] = back[j + 1] + 1;
else
back[j] = back[j + 1];
}
int mins = 100005;//找最小值
for (int i = 1; i < length - 1; i++)
{
mins = min(mins, fron[i] + back[i]);
}
cout << mins;
return 0;
}