给你一个由大小写英文字母组成的字符串 s 。
一个整理好的字符串中,两个相邻字符 s[i] 和 s[i + 1] 不会同时满足下述条件:
- 0 <= i <= s.length - 2
- s[i] 是小写字符,但 s[i + 1] 是相同的大写字符;反之亦然 。
请你将字符串整理好,每次你都可以从字符串中选出满足上述条件的 两个相邻 字符并删除,直到字符串整理好为止。
请返回整理好的 字符串 。题目保证在给出的约束条件下,测试样例对应的答案是唯一的。
注意:空字符串也属于整理好的字符串,尽管其中没有任何字符。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/make-the-string-great
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解法一
双指针,不过写的比较乱。
class Solution {
public String makeGood(String s) {
if (s.length() == 1) return s;
//双指针
char[] ch = s.toCharArray();
int index = 0; //当前比较的下标
int next = 1; //表示下个比较的位置下标
while (index < ch.length - 1 && next < ch.length) {
//如果是已经被删除的位置,直接跳过
if (ch[index] == '*' || ch[next] == '*') {
if (ch[index] == '*') index++;
if (ch[next] == '*') next++;
continue;
}
if (index == next) {
next++;
continue;
}
//比较是否互为大小写
if (ch[index] + 32 == ch[next] || ch[index] - 32 == ch[next]) {
//删除成功以后,需要比较拼接起来的两个字符是否互为大小写
ch[index] = '*';
ch[next] = '*';
//next:要向前一位
next++;
//index往后退一位,如果为'*',继续后退,一直到0
while (index > 0 && ch[index] == '*') index--;
//如果一直到0都是*,没有字符,那么index移到next的位置,next再加1
if (index == 0 && ch[index] == '*') {
index = next;
next++;
}
continue;
}
//如果不相同,都向前移一位
index++;
next++;
}
StringBuilder sb = new StringBuilder();
for (char c : ch) {
if (c != '*') sb.append(c);
}
//如果删除后长度为0,返回""
return sb.length() == 0 ? "" : sb.toString();
}
}
这个错误的次数,老踩坑师了。
解法二
看上图的运行错误次数就知道,解法一做完后,感觉身体被掏空~,然后逛了一下题解区,发现可以用栈来做,因为之前没怎么使用栈,没想到用栈来做,然后就自己写了一下,思路更清晰了,不过就是性能稍微差了些,比不了解法一。
class Solution {
public String makeGood(String s) {
if (s.length() == 1) return s;
//栈
char[] ch = s.toCharArray();
Stack<Character> stack = new Stack<>();
int index = 0;
while (index < ch.length) {
//如果栈为空,放入当前字符,然后进入下次循环
if (stack.empty()) {
stack.push(ch[index]);
index++;
continue;
}
//取出栈顶字符
char c = stack.pop();
//判断是否互为大小写
if (ch[index] + 32 == c || ch[index] - 32 == c) {
//不操作,进入下个循环
index++;
continue;
}
//不是互为大小写,把两个字符都压入到栈中
stack.push(c);
stack.push(ch[index]);
index++;
}
//如果比较完后,栈为空,返回""
if (stack.empty()) return "";
//把栈中的字符全部取出
StringBuilder sb = new StringBuilder();
while (!stack.empty()) {
sb.append(stack.pop());
}
return sb.reverse().toString();
}
}
虽然用栈效率稍微差了些,不过省去了一些不必要的判断,代码看起来也更加清晰。