题目描述
你的笔记本键盘存在故障,每当你在上面输入字符 'i'
时,它会反转你所写的字符串。而输入其他字符则可以正常工作。
给你一个下标从 0 开始的字符串 s
,请你用故障键盘依次输入每个字符。
返回最终笔记本屏幕上输出的字符串。
示例 1:
输入:s = "string" 输出:"rtsng" 解释: 输入第 1 个字符后,屏幕上的文本是:"s" 。 输入第 2 个字符后,屏幕上的文本是:"st" 。 输入第 3 个字符后,屏幕上的文本是:"str" 。 因为第 4 个字符是 'i' ,屏幕上的文本被反转,变成 "rts" 。 输入第 5 个字符后,屏幕上的文本是:"rtsn" 。 输入第 6 个字符后,屏幕上的文本是: "rtsng" 。 因此,返回 "rtsng" 。
示例 2:
输入:s = "poiinter" 输出:"ponter" 解释: 输入第 1 个字符后,屏幕上的文本是:"p" 。 输入第 2 个字符后,屏幕上的文本是:"po" 。 因为第 3 个字符是 'i' ,屏幕上的文本被反转,变成 "op" 。 因为第 4 个字符是 'i' ,屏幕上的文本被反转,变成 "po" 。 输入第 5 个字符后,屏幕上的文本是:"pon" 。 输入第 6 个字符后,屏幕上的文本是:"pont" 。 输入第 7 个字符后,屏幕上的文本是:"ponte" 。 输入第 8 个字符后,屏幕上的文本是:"ponter" 。 因此,返回 "ponter" 。
提示:
1 <= s.length <= 100
s
由小写英文字母组成s[0] != 'i'
1. 算法与思路
1.1 使用reverse方法直接进行模拟操作
public String finalString(String s) {
StringBuilder ans=new StringBuilder();
for(char c:s.toCharArray()){
if(c=='i')ans.reverse();
else ans.append(c);
}
return ans.toString();
}
1.2 使用双端队列进行模拟操作
1.2.1 思路
比较直观的思路是我们实时维护答案字符串 ans,当遇到非 “i” 的字符时,就将其加入字符串的末尾;否则将字符串进行反转。
然而字符串反转需要 O(l)的时间,其中 l 是当前 ans 的长度,这样做的时间复杂度较高。事实上,当字符串进行反转后,在末尾添加字符等价于「不对字符串进行反转,并且在开头添加字符」。因此,我们可以使用一个双端队列和一个布尔变量 head 来维护答案:
- 当遇到非 “i” 的字符时,如果 head 为真,就在队列的开头添加字符,否则在队列的末尾添加字符;
- 当遇到 “i” 时,将 head 取反。
head 的初始值为假。这样一来,每一个字符只需要 O(1) 的时间进行处理。
当处理完所有的字符后,如果 head 为真,那么将队列中的字符反序构造出答案字符串,否则正序构造出答案字符串。
1.2.2 代码
public String finalString(String s) {
Deque<Character> q = new ArrayDeque<Character>();
boolean head = false;
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (ch != 'i') {
if (head) {
q.offerFirst(ch);
} else {
q.offerLast(ch);
}
} else {
head = !head;
}
}
StringBuilder ans = new StringBuilder();
if (head) {
while (!q.isEmpty()) {
ans.append(q.pollLast());
}
} else {
while (!q.isEmpty()) {
ans.append(q.pollFirst());
}
}
return ans.toString();
}