通过万岁!!!
- 题目:给一个字符串,然后将里面的所有的?,替换为小写字母。要求,这个问号替换时,不能与前面和后面的字母重复。
- 思路:遍历字符串,找到问号就进行替换。这里可以替换成随意的,只要不是跟前面和后面的一样就行。我们最后定义一个规则,就是让她等于前面字母的下一个,如果超过z,就变成a。然后这样保证与前面的不一样,再去判断是不是与后面的不一样,如果一样也是变成下一个字母,也要判断是不是超过z。因为我们需要判断前一个和后一个,所以需要对最开始和最后的位置进行初始化。
- 技巧:
- 主要是定义一个规则,而这个规则尽量简单一点。
- 使用StringBuilder,因为我们要不断对字符串进行追加。或者是用一个char的数组应该也可以,数组长度为s的长度,最后将数组转成String返回,String有构造方法将char数组转成String。
- 注意:
- 我们要变成的是前面字母+1的位置,但是这个前面字母是我们最后要返回的结果(StringBuilder对象)的最后一位,这时候不能用题目中给定的字符串,因为前面的字符可能是?。
- 判断最后一位的时候,可能存在特殊问题,就是字符串长度为1,则考虑第一个的时候考虑了她,最后一个的时候也考虑了她,就会产生问题。
伪代码
定义StringBuilder的字符串sb
定义追加的字符temp
如果0是位置是?
如果长度大于或者等于2
temp='a';
然后判断是不是跟1位置的冲突,要是冲突就temp++,使其不冲突
然后temp追加到sb即可
否则,也就是长度等于1的时候
直接随便返回一个字母就可以了
否则,也就是0位置不是?
sb追加一下这个字符
然后遍历字符串,从1开始,到s的倒数第二位
如果是问号
temp=sb的最后位置+1,并且判断是不是超过了z(也就是122),超过了就改成a,没超过就不变,用三目表达式即可
判断temp是不是跟后面的字符一样,要是一样则temp也要++
这时候还需要再判断,因为++以后可能又超过z了。
然后再将temp追加到sb上
否则,也就是这个不是?,则直接之家即可
然后就是最后一个位置的判断了,如果是?
则temp变成sb的最后一个位置+1,并且这个也需要判断是不是超过z
然后temp追加到sb上即可
否则,应该就是直接追加,但是还有需要判断原字符串长度不能等于1,要求等于1的时候,才再考虑最后一个
sb追加原字符串的最后一个
return sb的toString()即可。
java代码
class Solution {
public String modifyString(String s) {
StringBuilder sb = new StringBuilder();
char temp;
if (s.charAt(0) == '?') {
if (s.length() >= 2) {
temp = 'a';
if (temp == s.charAt(1)) {// 与后面字母不同
temp++;
}
sb.append(temp);
} else {
return "a";
}
} else
sb.append(s.charAt(0));
for (int i = 1; i < s.length() - 1; i++) {
if (s.charAt(i) == '?') {
// 不与前面的相同
temp = (sb.charAt(sb.length() - 1) + 1) > 122 ? 'a' : (char) (sb.charAt(sb.length() - 1) + 1);
if (temp == s.charAt(i + 1)) {// 与后面字母不同
temp++;
}
temp = temp > 122 ? 'a' : temp;
sb.append(temp);
} else {
sb.append(s.charAt(i));
}
}
if (s.charAt(s.length() - 1) == '?') {
temp = (sb.charAt(sb.length() - 1) + 1) > 122 ? 'a' : (char) (sb.charAt(sb.length() - 1) + 1);
sb.append(temp);
} else if (s.length() != 1) {
sb.append(s.charAt(s.length() - 1));
}
return sb.toString();
}
}
- 总结:题目不复杂,就是比较麻烦而已。首先是自己定义一个选取的规则,然后就是判断前后。
接下来是不适用StringBuilder,而是使用char的数组的代码,这种的空间复杂度回降低很多。
class Solution {
public String modifyString(String s) {
char sb[] = new char[s.length()];
char temp;
if (s.charAt(0) == '?') {
if (s.length() >= 2) {
temp = 'a';
if (temp == s.charAt(1)) {// 与后面字母不同
temp++;
}
sb[0] = temp;
} else
return "a";
} else
sb[0] = s.charAt(0);
for (int i = 1; i < s.length() - 1; i++) {
if (s.charAt(i) == '?') {
// 不与前面的相同
temp = (sb[i - 1] + 1) > 122 ? 'a' : (char) (sb[i - 1] + 1);
if (temp == s.charAt(i + 1)) {// 与后面字母不同
temp++;
}
temp = temp > 122 ? 'a' : temp;
sb[i] = temp;
} else {
sb[i] = s.charAt(i);
}
}
if (s.charAt(s.length() - 1) == '?') {
temp = (sb[s.length() - 2] + 1) > 122 ? 'a' : (char) (sb[s.length() - 2] + 1);
sb[s.length() - 1] = temp;
} else if (s.length() != 1) {
sb[s.length() - 1] = s.charAt(s.length() - 1);
}
return new String(sb);
}
}
然后我又对多余的代码行删除了一下,得到了最终版。
class Solution {
public String modifyString(String s) {
char sb[] = new char[s.length()];
char temp;
if (s.charAt(0) == '?') {// 第一个是就是问号
if (s.length() >= 2) {// 还有后面字母
if ('a' == s.charAt(1)) // 后面字母是a
sb[0] = 'b';// 换个字母
else
sb[0] = 'a';// 用a就行
} else// 只有一个字符,并且还是问号
return "a";
} else// 第一个不是问好
sb[0] = s.charAt(0);
// 从第二个到倒数第二个开始遍历
for (int i = 1; i < s.length() - 1; i++) {
if (s.charAt(i) == '?') {
// 不与前面的相同
temp = (sb[i - 1] + 1) > 122 ? 'a' : (char) (sb[i - 1] + 1);
if (temp == s.charAt(i + 1)) {// 与后面字母不同
temp++;
}
sb[i] = temp > 122 ? 'a' : temp;
} else
sb[i] = s.charAt(i);
}
if (s.charAt(s.length() - 1) == '?') {// 下面不会越界,因为只有s=?的时候才会越界,而这时候,上面已经return了
sb[s.length() - 1] = (sb[s.length() - 2] + 1) > 122 ? 'a' : (char) (sb[s.length() - 2] + 1);
} else if (s.length() != 1) {
sb[s.length() - 1] = s.charAt(s.length() - 1);
}
return new String(sb);
}
}