【LeetCode 算法】Remove Comments 删除注释-模拟

Remove Comments 删除注释

问题描述:

给一个 C++ 程序,删除程序中的注释。这个程序source是一个数组,其中source[i]表示第 i 行源码。 这表示每行源码由 ‘\n’ 分隔。

在 C++ 中有两种注释风格,行内注释和块注释。

字符串// 表示行注释,表示//和其右侧的其余字符应该被忽略。
字符串/* 表示一个块注释,它表示直到下一个(非重叠)出现的*/之间的所有字符都应该被忽略。(阅读顺序为从左到右)非重叠是指,字符串/*/并没有结束块注释,因为注释的结尾与开头相重叠。
第一个有效注释优先于其他注释。

如果字符串//出现在块注释中会被忽略。
同样,如果字符串/*出现在行或块注释中也会被忽略。
如果一行在删除注释之后变为空字符串,那么不要输出该行。即,答案列表中的每个字符串都是非空的。

样例中没有控制字符,单引号或双引号字符。

比如,source = “string s = “/* Not a comment. */”;” 不会出现在测试样例里。
此外,没有其他内容(如定义或宏)会干扰注释。

我们保证每一个块注释最终都会被闭合, 所以在行或块注释之外的/*总是开始新的注释。

最后,隐式换行符可以通过块注释删除。 有关详细信息,请参阅下面的示例。

从源代码中删除注释后,需要以相同的格式返回源代码。

1 < = s o u r c e . l e n g t h < = 100 0 < = s o u r c e [ i ] . l e n g t h < = 80 s o u r c e [ i ] 由可打印的 A S C I I 字符组成。 每个块注释都会被闭合。 给定的源码中不会有单引号、双引号或其他控制字符。 1 <= source.length <= 100\\ 0 <= source[i].length <= 80\\ source[i] 由可打印的 ASCII 字符组成。\\ 每个块注释都会被闭合。\\ 给定的源码中不会有单引号、双引号或其他控制字符。 1<=source.length<=1000<=source[i].length<=80source[i]由可打印的ASCII字符组成。每个块注释都会被闭合。给定的源码中不会有单引号、双引号或其他控制字符。

分析

一个模拟问题.

对于每一行代码,有可能存在注释,块注释或者是行注释.
也可能不存在注释,但是需要注意即使本行不存在注释,它也有可能属于块注释的一部分.

如果之前没有出现过块注释,那么接下来的代码中可能出现 纯代码 , 第一个块注释,行注释,代码+注释等,

  • 纯代码,就是决对不会出现 / / , / ∗ //,/* //,/, 由于之前没有注释,所以这里不会出现 ∗ / */ /.
  • 行注释,此位置后的都可以忽略。
  • 第一部分块注释,即 / ∗ /* /会出现,那么需要找到他的结尾 ∗ / */ /,end 可能在当前行尾,或者是下面的某行中。

为了解决这个问题,官方的思路,比较精简,它将块注释使用标记,那么字符要么在注释内,要么不在注释内。而行注释可以直接删除后面的内容。

  • 如果 i n B l o c k = t r u e , inBlock=true, inBlock=true,表示处于块注释中,非注释标记的字符都不会加入字符串,而且只需要关心是否会遇到*/,从而结束块注释。
  • 如果 i n B l o c k = f a l s e , inBlock=false, inBlock=false,表示不在块注释中,也就是说 当前行中可能有代码,也有可能有行注释,当然也有可能遇到 块注释的开始位置。

如果一行处理完成,只有当不处于块注释的状态下并且字符串不为空的情况下,才会进行输出,同时还要清空字符串。

代码

public List<String> removeComments(String[] source) {
        boolean inBlock = false;
        StringBuilder newline = new StringBuilder();
        List<String> ans = new ArrayList();
        for (String line: source) {
            int i = 0;
            char[] chars = line.toCharArray();
            if (!inBlock) newline = new StringBuilder();
            while (i < line.length()) {
                if (!inBlock && i+1 < line.length() && chars[i] == '/' && chars[i+1] == '*') {
                    inBlock = true;
                    i++;
                } else if (inBlock && i+1 < line.length() && chars[i] == '*' && chars[i+1] == '/') {
                    inBlock = false;
                    i++;
                } else if (!inBlock && i+1 < line.length() && chars[i] == '/' && chars[i+1] == '/') {
                    break;
                } else if (!inBlock) {
                    newline.append(chars[i]);
                }
                i++;
            }
            if (!inBlock && newline.length() > 0) {
                ans.add(new String(newline));
            }
        }
        return ans;
    }

时间复杂度 O ( M N ) O(MN) O(MN)

空间复杂度 O ( M N ) O(MN) O(MN)

Tag

Array

String

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Eric.Cui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值