Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e3444f5

Browse files
[新增] 新增题目 722. 删除注释
1 parent 52b773f commit e3444f5

File tree

3 files changed

+152
-0
lines changed

3 files changed

+152
-0
lines changed

‎src/722_removeComments.ts

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import testCases from '../tests/testCases/722_removeComments'
2+
3+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
4+
`
5+
722. 删除注释
6+
https://leetcode.cn/problems/remove-comments/
7+
难度:中等
8+
9+
给一个 C++ 程序,删除程序中的注释。这个程序source是一个数组,其中source[i]表示第 i 行源码。 这表示每行源码由 '\n' 分隔。
10+
在 C++ 中有两种注释风格,行内注释和块注释。
11+
字符串// 表示行注释,表示//和其右侧的其余字符应该被忽略。
12+
字符串/* 表示一个块注释,它表示直到下一个(非重叠)出现的*/之间的所有字符都应该被忽略。(阅读顺序为从左到右)非重叠是指,字符串/*/并没有结束块注释,因为注释的结尾与开头相重叠。
13+
第一个有效注释优先于其他注释。
14+
15+
如果字符串//出现在块注释中会被忽略。
16+
同样,如果字符串/*出现在行或块注释中也会被忽略。
17+
如果一行在删除注释之后变为空字符串,那么不要输出该行。即,答案列表中的每个字符串都是非空的。
18+
19+
样例中没有控制字符,单引号或双引号字符。
20+
比如,source = "string s = "/* Not a comment. */";" 不会出现在测试样例里。
21+
此外,没有其他内容(如定义或宏)会干扰注释。
22+
23+
我们保证每一个块注释最终都会被闭合, 所以在行或块注释之外的/*总是开始新的注释。
24+
最后,隐式换行符可以通过块注释删除。 有关详细信息,请参阅下面的示例。
25+
从源代码中删除注释后,需要以相同的格式返回源代码。
26+
27+
示例 1:
28+
输入: source = ["/*Test program */", "int main()", "{ ", " // variable declaration ", "int a, b, c;", "/* This is a test", " multiline ", " comment for ", " testing */", "a = b + c;", "}"]
29+
输出: ["int main()","{ "," ","int a, b, c;","a = b + c;","}"]
30+
解释: 示例代码可以编排成这样:
31+
/*Test program */
32+
int main()
33+
{
34+
// variable declaration
35+
int a, b, c;
36+
/* This is a test
37+
multiline
38+
comment for
39+
testing */
40+
a = b + c;
41+
}
42+
第 1 行和第 6-9 行的字符串 /* 表示块注释。第 4 行的字符串 // 表示行注释。
43+
编排后:
44+
int main()
45+
{
46+
47+
int a, b, c;
48+
a = b + c;
49+
}
50+
51+
示例 2:
52+
输入: source = ["a/*comment", "line", "more_comment*/b"]
53+
输出: ["ab"]
54+
解释: 原始的 source 字符串是 "a/*comment\nline\nmore_comment*/b", 其中我们用粗体显示了换行符。删除注释后,隐含的换行符被删除,留下字符串 "ab" 用换行符分隔成数组时就是 ["ab"].
55+
56+
提示:
57+
1 <= source.length <= 100
58+
0 <= source[i].length <= 80
59+
source[i] 由可打印的 ASCII 字符组成。
60+
每个块注释都会被闭合。
61+
给定的源码中不会有单引号、双引号或其他控制字符。
62+
`
63+
64+
/**
65+
* 去除 C++ 程序的注释
66+
* - LeetCode 入口
67+
* @param {string[]} source - 源码行数组
68+
* @returns {string[]} 去除注释后的代码行数组
69+
*/
70+
function removeComments (source: string[]): string[] {
71+
// 使用换行符合并所有代码行
72+
const sourceString = source.join('\n')
73+
74+
// 初始化状态
75+
let charIndex = 0
76+
let isString = false
77+
let resultString = ''
78+
79+
// 遍历代码字符
80+
while (charIndex < sourceString.length) {
81+
// 获取当前字符与下一个字符
82+
const currentChar = sourceString[charIndex]
83+
const nextChar = sourceString[charIndex + 1]
84+
85+
// 1. 设置字符串状态
86+
if (currentChar === '"') isString = !isString
87+
88+
// 2. 跳过单行注释(不为字符串时,判断当前字符与下一个字符的组合是否为"//")
89+
if (!isString && (currentChar + nextChar === '//')) {
90+
// 寻找下一个换行符的位置
91+
const nextIndex = sourceString.indexOf('\n', charIndex)
92+
// 找不到下一个换行符则说明直到代码结束都不在有换行符,直接结束遍历
93+
if (nextIndex === -1) break
94+
// 将字符索引设置为下一个换行符
95+
charIndex = nextIndex
96+
continue
97+
}
98+
99+
// 3. 跳过多行注释(不为字符串时,判断当前字符与下一个字符的组合是否为 "/*")
100+
if (!isString && (currentChar + nextChar === '/*')) {
101+
// 将字符索引设置为下一个 "*/" 之后,开始查找的索引为当前 "/*" 之后
102+
const nextIndex = sourceString.indexOf('*/', charIndex + 2)
103+
if (nextIndex === -1) break
104+
charIndex = nextIndex + 2
105+
continue
106+
}
107+
108+
// 将当前字符添加至去除注释的代码字符串
109+
resultString += currentChar
110+
charIndex += 1
111+
}
112+
113+
// 使用换行符拆分去除注释后的代码字符串并去除空行
114+
return resultString.split('\n').filter(line => line !== '')
115+
}
116+
117+
// Debug
118+
if (require.main === module) {
119+
const testCase = testCases[0]
120+
console.log({ input: testCase.input, output: removeComments(testCase.input), expected: testCase.expected })
121+
}
122+
123+
export { removeComments }

‎tests/722_removeComments.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { describe, test, expect } from '@jest/globals'
2+
import testCases from './testCases/722_removeComments'
3+
import { removeComments } from '../src/722_removeComments'
4+
5+
describe('722. Remove Comments', () => {
6+
testCases.forEach((testCase, index) => {
7+
test(`Test case index: ${index}`, () => {
8+
expect(removeComments(testCase.input)).toEqual(testCase.expected)
9+
})
10+
})
11+
})

‎tests/testCases/722_removeComments.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
export default [
2+
{
3+
input: ['/*Test program */', 'int main()', '{ ', ' // variable declaration ', 'int a, b, c;', '/* This is a test', ' multiline ', ' comment for ', ' testing */', 'a = b + c;', '}'],
4+
expected: ['int main()', '{ ', ' ', 'int a, b, c;', 'a = b + c;', '}']
5+
},
6+
{
7+
input: ['a/*comment', 'line', 'more_comment*/b'],
8+
expected: ['ab']
9+
},
10+
{
11+
input: ['struct Node{', ' /*/ declare members;/**/', ' int size;', ' /**/int val;', '};'],
12+
expected: ['struct Node{', ' ', ' int size;', ' int val;', '};']
13+
},
14+
{
15+
input: ['a//*b//*c', 'blank', 'd//*e/*/f'],
16+
expected: ['a', 'blank', 'd']
17+
}
18+
]

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /