双端队列--故障键盘

题目描述

你的笔记本键盘存在故障,每当你在上面输入字符 '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();
    }

2. 参考题目

. - 力扣(LeetCode)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值