每日一题:故障键盘

你的笔记本键盘存在故障,每当你在上面输入字符 '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()};
    }
};
  • 18
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值