你的笔记本键盘存在故障,每当你在上面输入字符 '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'
最近在从java转向c++,通过这道题可以学习c++双端队列的使用方法。
C++双端队列
双端队列(deque,发音为“deck”)是一种线性数据结构,它允许在队列的两端进行高效的插入和删除操作。它结合了队列和栈的特性,支持以下操作:
- 在队首(front)插入和删除元素
- 在队尾(back)插入和删除元素
- 随机访问元素
C++ 中的双端队列:
C++ 标准库中提供了 std::deque
类来实现双端队列。它是一个基于模板的容器,可以存储任何类型的元素。
主要成员函数:
- push_front(const T& value):在队首插入一个元素。
- push_back(const T& value):在队尾插入一个元素。
- pop_front(): 删除队首的元素。
- pop_back(): 删除队尾的元素。
- front(): 返回队首元素的引用。
- back(): 返回队尾元素的引用。
- empty(): 检查双端队列是否为空。
- size(): 返回双端队列中元素的数量。
针对本题,考虑如下:
- 没有遇到 i 时,将s中的每一个字符正向添加到结果result中。
- 当遇到 i 时会发生什么?
以abcdief为例,按照规则,应该输出dcbaef。
向result数组中添加字符过程如下:abcd,此时遇到 i ,应当反转字符串。那么实际上就是将输出从正向变成反向(dcba)。为了节省此步骤的开销,不真的将字符串反转,而是使用一个bool变量from_head标记当前方向,初始化为true,此变量每次遇到 i 时取反。
当result被记录成反向时,就在双端队列的队首插入,将对应字符添加到result头部。
也就是说:字符串进行反转后,在末尾添加字符等价于「不对字符串进行反转,并且在开头添加字符」
- 接着上面的例子,遇到 i 时,result中保存的将是feabcd,而此时from_head为false。在输出结果时需要使用反向迭代器。
- 因此,遇到 i 时,将from_head取反。当from_head为true时,说明结果是正向,且字符需要添加到队尾;当from_head为false时,结果是反向,且字符需要添加到队首。
代码:
class Solution {
public:
string finalString(string s) {
std::deque<char> dq;
bool from_head = true;
for(char c: s){
if(c == 'i'){
from_head = !from_head;
continue;
}
if(from_head){
dq.push_back(c);
}else{
dq.push_front(c);
}
}
return from_head ? string{dq.begin(),dq.end()} : string{dq.rbegin(),dq.rend()};
}
};