问题描述
小C手中有一个由小写字母组成的字符串 s。她希望构造另一个字符串 t,并且这个字符串需要满足以下几个条件:
t由小写字母组成,且长度与s相同。t是回文字符串,即从左到右与从右到左读取相同。t的字典序要小于s,并且在所有符合条件的字符串中字典序尽可能大。
小C想知道是否能构造出这样的字符串 t,输出这样的t。如果无法构造满足条件的字符串,则输出 -1。
测试样例
样例1:
输入:
s = "abc"
输出:'aba'
样例2:
输入:
s = "cba"
输出:'cac'
样例3:
输入:
s = "aaa"
输出:'-1'
问题分析
题目要求在满足条件的情况下,尽可能的使字符串的字典序最大,这满足贪心算法的策略。根据题目的要求,需要字典序最大,量度指标为每次保证字符串前面的字符尽可能大。分析题目条件:
- t的字典序要小于s,这表明t从左到右的每个字符不能超过s对应的位置的字符。
- t是回文字符串,即从左到右和从右到左的读取相同。
- t的长度与s相同,因此比较t和s字符串是最需要一一比较相同索引的字符。
由此,我们考虑一下步骤:
- 首先构建一个初始的回文字符串t,由于t不能大于s,因此遍历s前面一半的字符串,s[i] = s[length-1]构建回文字符串。
- 构建的t有三种情况:(1)如果t小于s,那么直接满足条件。(2)如果s所有字符都为'a',t无法小于s,则输出为-1。(3)如果t大于或者等于s。那么需要将满足条件的最小位置的字符-1,保存其他位置字符尽可能大,这样导致的损失最小。
- 最小位置应该是中间位置,即t[length/2],但是如果t[length/2] = 'a',无法减小,那么需要向前考虑一位,直到t[index] > 'a' 则,t[index] = t[index] - 1。对应的t[length - 1-index] = t[index]修改。修改后无论index后面的字符多大,t都小于s,则将t[index+1] 到 t[length - index]直接的所有字符修改成最大值'z'。
完整代码如下
public class Main {
public static String solution(String s) {
// write code here
int length = s.length();
char[] str = s.toCharArray();
char[] tmp = new char[length];
int flag = 0; // str和tmp相同
for(int i=0; i<length/2; i++){
tmp[i] = str[i];
tmp[length-i-1] = str[i];
if(tmp[length-1-i] > str[length-1-i])
flag = 1; // str 小于 tmp
else if(tmp[length-1-i] < str[length-1-i])
flag = 2; // str 大于 tmp
}
// 考虑长度为奇数和偶数的情况。
if(length%2 == 1)
tmp[length/2] = str[length/2]; // 奇数长度的字符串,tmp[length/2] = str[length/2]
if(flag == 0 || flag == 1){
int index = length/2;
while(index < length){
if(tmp[index] != 'a'){ // 找到能够使t小于s的最小索引位置。
tmp[index] = (char)(tmp[index] - 1);
tmp[length - 1 - index] = tmp[index];
break;
}
index++;
}
if(index == length)
return "-1";
index--;
while(index >= length/2){ // 返回来将中间字符取最高值。
tmp[index] = 'z';
tmp[length - 1 - index] = tmp[index];
index--;
}
}
String result = "";
for(char c : tmp){
result += c;
}
// System.out.println(result);
return result;
}
public static void main(String[] args) {
System.out.println(solution("abc").equals("aba"));
System.out.println(solution("cba").equals("cac"));
System.out.println(solution("aaa").equals("-1"));
}
}
问题总结
这题主要考察问题分析能力,涵盖字符串回文特性、贪心算法、边界条件处理的知识点,在编写代码时,需要注意细节问题,例如奇数长度和偶数长度中间值的索引如何表示,如果仔细可能会存在错误。
(个人总结,有问题请指出)