一、问题描述
题目描述
游戏规则:输入一个只包含英文字母的字符串,字符串中的两个字母如果相邻且相同,就可以消除。
在字符串上反复执行消除的动作,直到无法继续消除为止,此时游戏结束。
输出最终得到的字符串长度。
输入描述
输入原始字符串 str
,只能包含大小写英文字母,字母的大小写敏感,str
长度不超过100。
输出描述
输出游戏结束后,最终得到的字符串长度。
备注
输入中包含非大小写英文字母时,均为异常输入,直接返回 0。
用例
用例 1
输入:
gg
输出:
0
说明:
gg
可以直接消除,得到空串,长度为 0。
用例 2
输入:
mMbccbc
输出:
3
说明:
在 mMbccbc
中,可以先消除 cc
;
此时字符串变成 mMbbc
,可以再消除 bb
;
此时字符串变成 mMc
,此时没有相邻且相同的字符,无法继续消除。
最终得到的字符串为 mMc
,长度为 3。
题目解析
这题比较容易地解法是利用栈结构。
即先创建一个栈,然后遍历输入的字符串,将每一个字符尝试压入栈,但是压入前,需要判断,栈顶元素是否和将要压入的字符相同,若不同,则压入,若相同,则字符不压入,且栈顶元素弹出。
由于这题只要遇到两两相邻相同的字符就会消除,比如 acccb
,消除后就变为了 acb
,因此遇到 >2 的奇数个相同相邻字符,是无法消除完的,总是会遗留一个。
注意,遍历的字符如果是非字母,则直接返回 0。
详细步骤
-
读取输入:
- 从标准输入读取一个字符串
str
。
- 从标准输入读取一个字符串
-
检查输入合法性:
- 如果字符串中包含非字母字符,直接返回 0。
-
初始化栈:
- 创建一个空栈
stack
,用于存储字符。
- 创建一个空栈
-
遍历字符串:
- 遍历字符串中的每个字符
char
:- 如果
stack
不为空且stack
的栈顶元素与char
相同,弹出栈顶元素。 - 否则,将
char
压入栈中。
- 如果
- 遍历字符串中的每个字符
-
输出结果:
- 输出栈的长度,即最终字符串的长度。
用例解释
用例 1
- 输入:
gg
- 输出:
0
解释:
- 遍历字符串
gg
:g
-> 压入栈中,栈:[g]
g
-> 栈顶元素为g
,弹出栈顶元素,栈:[]
- 最终栈为空,长度为 0。
用例 2
- 输入:
mMbccbc
- 输出:
3
解释:
- 遍历字符串
mMbccbc
:m
-> 压入栈中,栈:[m]
M
-> 压入栈中,栈:[m, M]
b
-> 压入栈中,栈:[m, M, b]
c
-> 压入栈中,栈:[m, M, b, c]
c
-> 栈顶元素为c
,弹出栈顶元素,栈:[m, M, b]
b
-> 栈顶元素为b
,弹出栈顶元素,栈:[m, M]
c
-> 压入栈中,栈:[m, M, c]
- 最终栈为
[m, M, c]
,长度为 3。
通过上述步骤,我们可以高效地求出最终字符串的长度。这种方法的时间复杂度为 O(n)
,其中 n
是字符串的长度。
二、JavaScript算法源码
以下是 JavaScript 代码 的详细中文注释和逻辑讲解:
JavaScript 代码
/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline"); // 引入 readline 模块,用于读取控制台输入
// 创建 readline 接口
const rl = readline.createInterface({
input: process.stdin, // 输入流为标准输入
output: process.stdout, // 输出流为标准输出
});
// 监听 'line' 事件,当用户输入一行内容时触发
rl.on("line", (line) => {
console.log(getResult(line)); // 调用 getResult 方法处理输入,并输出结果
});
/**
* 计算字符串中未匹配字符的数量
* @param {string} s 输入的字符串
* @returns {number} 未匹配字符的数量
*/
function getResult(s) {
const stack = []; // 使用数组模拟栈
// 遍历字符串中的每个字符
for (let c of s) {
// 检查字符是否为字母(A-Z 或 a-z)
if (c < "A" || c > "z" || (c > "Z" && c < "a")) {
return 0; // 如果字符不是字母,直接返回 0
}
// 如果栈不为空且当前字符与栈顶字符相同
if (stack.length > 0 && stack.at(-1) == c) {
stack.pop(); // 移除栈顶字符(匹配成功)
} else {
stack.push(c); // 将当前字符压入栈中(未匹配)
}
}
return stack.length; // 返回栈中剩余的未匹配字符数量
}
代码逻辑讲解
1. 输入处理
- 使用
readline
模块读取控制台输入。 - 监听
'line'
事件,当用户输入一行内容时,调用getResult
方法处理输入,并输出结果。
2. 字符匹配逻辑
- 使用数组
stack
模拟栈的行为:- 栈用于存储未匹配的字符。
- 如果当前字符与栈顶字符相同,则匹配成功,移除栈顶字符。
- 如果当前字符与栈顶字符不同,则将当前字符压入栈中。
3. 字符有效性检查
- 检查当前字符是否为字母(
A-Z
或a-z
):- 如果字符不是字母,直接返回
0
。 - 这是为了确保输入字符串中只包含字母。
- 如果字符不是字母,直接返回
4. 返回结果
- 最终返回栈中剩余的未匹配字符数量:
- 如果栈为空,说明所有字符都匹配成功。
- 如果栈不为空,说明栈中剩余的字符未匹配。
示例验证
示例 1:s = “abba”
- 遍历过程:
- 字符
'a'
:压入栈中,栈内容:['a']
。 - 字符
'b'
:压入栈中,栈内容:['a', 'b']
。 - 字符
'b'
:与栈顶字符'b'
匹配,移除栈顶字符,栈内容:['a']
。 - 字符
'a'
:与栈顶字符'a'
匹配,移除栈顶字符,栈内容:[]
。
- 字符
- 结果:
stack.length = 0
(所有字符匹配成功)。
示例 2:s = “abc”
- 遍历过程:
- 字符
'a'
:压入栈中,栈内容:['a']
。 - 字符
'b'
:压入栈中,栈内容:['a', 'b']
。 - 字符
'c'
:压入栈中,栈内容:['a', 'b', 'c']
。
- 字符
- 结果:
stack.length = 3
(所有字符未匹配)。
示例 3:s = “aabbcc”
- 遍历过程:
- 字符
'a'
:压入栈中,栈内容:['a']
。 - 字符
'a'
:与栈顶字符'a'
匹配,移除栈顶字符,栈内容:[]
。 - 字符
'b'
:压入栈中,栈内容:['b']
。 - 字符
'b'
:与栈顶字符'b'
匹配,移除栈顶字符,栈内容:[]
。 - 字符
'c'
:压入栈中,栈内容:['c']
。 - 字符
'c'
:与栈顶字符'c'
匹配,移除栈顶字符,栈内容:[]
。
- 字符
- 结果:
stack.length = 0
(所有字符匹配成功)。
总结
- 功能:统计字符串中未匹配字符的数量。
- 核心逻辑:
- 使用栈来匹配相邻的相同字符。
- 如果字符匹配成功,移除栈顶字符;否则,将字符压入栈中。
- 最终返回栈中剩余的未匹配字符数量。
- 适用场景:需要检查字符串中是否存在未匹配的字符。
- 注意事项:
- 输入字符串只能包含字母(
A-Z
或a-z
)。 - 如果字符串为空,结果为
0
。
- 输入字符串只能包含字母(
如果有其他问题,欢迎随时提问!
三、Java算法源码
以下是 Java 代码 的详细中文注释和逻辑讲解:
Java 代码
import java.util.LinkedList; // 引入 LinkedList 类,用于实现栈的功能
import java.util.Scanner; // 引入 Scanner 类,用于读取用户输入
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in); // 创建 Scanner 对象,用于读取控制台输入
System.out.println(getResult(sc.nextLine())); // 读取一行输入并调用 getResult 方法,输出结果
}
/**
* 计算字符串中未匹配字符的数量
* @param s 输入的字符串
* @return 未匹配字符的数量
*/
public static int getResult(String s) {
LinkedList<Character> stack = new LinkedList<>(); // 使用 LinkedList 模拟栈
// 遍历字符串中的每个字符
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i); // 获取当前字符
// 检查字符是否为字母(A-Z 或 a-z)
if (c < 'A' || c > 'z' || (c > 'Z' && c < 'a')) {
return 0; // 如果字符不是字母,直接返回 0
}
// 如果栈不为空且当前字符与栈顶字符相同
if (stack.size() > 0 && c == stack.getLast()) {
stack.removeLast(); // 移除栈顶字符(匹配成功)
} else {
stack.addLast(c); // 将当前字符压入栈中(未匹配)
}
}
return stack.size(); // 返回栈中剩余的未匹配字符数量
}
}
代码逻辑讲解
1. 输入处理
- 使用
Scanner
类从控制台读取一行输入,并将其作为参数传递给getResult
方法。
2. 字符匹配逻辑
- 使用
LinkedList
模拟栈的行为:- 栈用于存储未匹配的字符。
- 如果当前字符与栈顶字符相同,则匹配成功,移除栈顶字符。
- 如果当前字符与栈顶字符不同,则将当前字符压入栈中。
3. 字符有效性检查
- 检查当前字符是否为字母(
A-Z
或a-z
):- 如果字符不是字母,直接返回
0
。 - 这是为了确保输入字符串中只包含字母。
- 如果字符不是字母,直接返回
4. 返回结果
- 最终返回栈中剩余的未匹配字符数量:
- 如果栈为空,说明所有字符都匹配成功。
- 如果栈不为空,说明栈中剩余的字符未匹配。
示例验证
示例 1:s = “abba”
- 遍历过程:
- 字符
'a'
:压入栈中,栈内容:['a']
。 - 字符
'b'
:压入栈中,栈内容:['a', 'b']
。 - 字符
'b'
:与栈顶字符'b'
匹配,移除栈顶字符,栈内容:['a']
。 - 字符
'a'
:与栈顶字符'a'
匹配,移除栈顶字符,栈内容:[]
。
- 字符
- 结果:
stack.size() = 0
(所有字符匹配成功)。
示例 2:s = “abc”
- 遍历过程:
- 字符
'a'
:压入栈中,栈内容:['a']
。 - 字符
'b'
:压入栈中,栈内容:['a', 'b']
。 - 字符
'c'
:压入栈中,栈内容:['a', 'b', 'c']
。
- 字符
- 结果:
stack.size() = 3
(所有字符未匹配)。
示例 3:s = “aabbcc”
- 遍历过程:
- 字符
'a'
:压入栈中,栈内容:['a']
。 - 字符
'a'
:与栈顶字符'a'
匹配,移除栈顶字符,栈内容:[]
。 - 字符
'b'
:压入栈中,栈内容:['b']
。 - 字符
'b'
:与栈顶字符'b'
匹配,移除栈顶字符,栈内容:[]
。 - 字符
'c'
:压入栈中,栈内容:['c']
。 - 字符
'c'
:与栈顶字符'c'
匹配,移除栈顶字符,栈内容:[]
。
- 字符
- 结果:
stack.size() = 0
(所有字符匹配成功)。
总结
- 功能:统计字符串中未匹配字符的数量。
- 核心逻辑:
- 使用栈来匹配相邻的相同字符。
- 如果字符匹配成功,移除栈顶字符;否则,将字符压入栈中。
- 最终返回栈中剩余的未匹配字符数量。
- 适用场景:需要检查字符串中是否存在未匹配的字符。
- 注意事项:
- 输入字符串只能包含字母(
A-Z
或a-z
)。 - 如果字符串为空,结果为
0
。
- 输入字符串只能包含字母(
如果有其他问题,欢迎随时提问!
四、Python算法源码
以下是 Python 代码 的详细中文注释和逻辑讲解:
Python 代码
# 输入获取
s = input() # 从控制台读取一行输入,存储到变量 s 中
# 算法入口
def getResult():
stack = [] # 使用列表模拟栈
# 遍历字符串中的每个字符
for c in s:
# 检查字符是否为字母(A-Z 或 a-z)
if c < 'A' or c > 'z' or ('Z' < c < 'a'):
return 0 # 如果字符不是字母,直接返回 0
# 如果栈不为空且当前字符与栈顶字符相同
if len(stack) > 0 and stack[-1] == c:
stack.pop() # 移除栈顶字符(匹配成功)
else:
stack.append(c) # 将当前字符压入栈中(未匹配)
return len(stack) # 返回栈中剩余的未匹配字符数量
# 算法调用
print(getResult()) # 调用 getResult 方法并输出结果
代码逻辑讲解
1. 输入处理
- 使用
input()
函数从控制台读取一行输入,并将其存储到变量s
中。
2. 字符匹配逻辑
- 使用列表
stack
模拟栈的行为:- 栈用于存储未匹配的字符。
- 如果当前字符与栈顶字符相同,则匹配成功,移除栈顶字符。
- 如果当前字符与栈顶字符不同,则将当前字符压入栈中。
3. 字符有效性检查
- 检查当前字符是否为字母(
A-Z
或a-z
):- 如果字符不是字母,直接返回
0
。 - 这是为了确保输入字符串中只包含字母。
- 如果字符不是字母,直接返回
4. 返回结果
- 最终返回栈中剩余的未匹配字符数量:
- 如果栈为空,说明所有字符都匹配成功。
- 如果栈不为空,说明栈中剩余的字符未匹配。
示例验证
示例 1:s = “abba”
- 遍历过程:
- 字符
'a'
:压入栈中,栈内容:['a']
。 - 字符
'b'
:压入栈中,栈内容:['a', 'b']
。 - 字符
'b'
:与栈顶字符'b'
匹配,移除栈顶字符,栈内容:['a']
。 - 字符
'a'
:与栈顶字符'a'
匹配,移除栈顶字符,栈内容:[]
。
- 字符
- 结果:
len(stack) = 0
(所有字符匹配成功)。
示例 2:s = “abc”
- 遍历过程:
- 字符
'a'
:压入栈中,栈内容:['a']
。 - 字符
'b'
:压入栈中,栈内容:['a', 'b']
。 - 字符
'c'
:压入栈中,栈内容:['a', 'b', 'c']
。
- 字符
- 结果:
len(stack) = 3
(所有字符未匹配)。
示例 3:s = “aabbcc”
- 遍历过程:
- 字符
'a'
:压入栈中,栈内容:['a']
。 - 字符
'a'
:与栈顶字符'a'
匹配,移除栈顶字符,栈内容:[]
。 - 字符
'b'
:压入栈中,栈内容:['b']
。 - 字符
'b'
:与栈顶字符'b'
匹配,移除栈顶字符,栈内容:[]
。 - 字符
'c'
:压入栈中,栈内容:['c']
。 - 字符
'c'
:与栈顶字符'c'
匹配,移除栈顶字符,栈内容:[]
。
- 字符
- 结果:
len(stack) = 0
(所有字符匹配成功)。
总结
- 功能:统计字符串中未匹配字符的数量。
- 核心逻辑:
- 使用栈来匹配相邻的相同字符。
- 如果字符匹配成功,移除栈顶字符;否则,将字符压入栈中。
- 最终返回栈中剩余的未匹配字符数量。
- 适用场景:需要检查字符串中是否存在未匹配的字符。
- 注意事项:
- 输入字符串只能包含字母(
A-Z
或a-z
)。 - 如果字符串为空,结果为
0
。
- 输入字符串只能包含字母(
如果有其他问题,欢迎随时提问!
五、C/C++算法源码:
以下是 C++ 代码 和 C 语言代码 的实现,并附带详细的中文注释和逻辑讲解:
C++ 代码
#include <iostream>
#include <stack>
using namespace std;
// 算法入口
int getResult(string s) {
stack<char> st; // 使用栈来存储未匹配的字符
// 遍历字符串中的每个字符
for (char c : s) {
// 检查字符是否为字母(A-Z 或 a-z)
if (c < 'A' || c > 'z' || (c > 'Z' && c < 'a')) {
return 0; // 如果字符不是字母,直接返回 0
}
// 如果栈不为空且当前字符与栈顶字符相同
if (!st.empty() && st.top() == c) {
st.pop(); // 移除栈顶字符(匹配成功)
} else {
st.push(c); // 将当前字符压入栈中(未匹配)
}
}
return st.size(); // 返回栈中剩余的未匹配字符数量
}
int main() {
string s;
cin >> s; // 从控制台读取输入字符串
cout << getResult(s) << endl; // 调用 getResult 方法并输出结果
return 0;
}
C 语言代码
#include <stdio.h>
#include <string.h>
#define MAX_SIZE 1000 // 定义栈的最大容量
// 算法入口
int getResult(char* s) {
char stack[MAX_SIZE]; // 使用数组模拟栈
int top = -1; // 栈顶指针,初始化为 -1 表示栈为空
// 遍历字符串中的每个字符
for (int i = 0; s[i] != '\0'; i++) {
char c = s[i];
// 检查字符是否为字母(A-Z 或 a-z)
if (c < 'A' || c > 'z' || (c > 'Z' && c < 'a')) {
return 0; // 如果字符不是字母,直接返回 0
}
// 如果栈不为空且当前字符与栈顶字符相同
if (top >= 0 && stack[top] == c) {
top--; // 移除栈顶字符(匹配成功)
} else {
stack[++top] = c; // 将当前字符压入栈中(未匹配)
}
}
return top + 1; // 返回栈中剩余的未匹配字符数量
}
int main() {
char s[MAX_SIZE];
scanf("%s", s); // 从控制台读取输入字符串
printf("%d\n", getResult(s)); // 调用 getResult 方法并输出结果
return 0;
}
代码逻辑讲解
1. 输入处理
- C++:使用
cin
从控制台读取输入字符串。 - C 语言:使用
scanf
从控制台读取输入字符串。
2. 字符匹配逻辑
- 使用栈来存储未匹配的字符:
- 如果当前字符与栈顶字符相同,则匹配成功,移除栈顶字符。
- 如果当前字符与栈顶字符不同,则将当前字符压入栈中。
3. 字符有效性检查
- 检查当前字符是否为字母(
A-Z
或a-z
):- 如果字符不是字母,直接返回
0
。 - 这是为了确保输入字符串中只包含字母。
- 如果字符不是字母,直接返回
4. 返回结果
- 最终返回栈中剩余的未匹配字符数量:
- 如果栈为空,说明所有字符都匹配成功。
- 如果栈不为空,说明栈中剩余的字符未匹配。
示例验证
示例 1:s = “abba”
- 遍历过程:
- 字符
'a'
:压入栈中,栈内容:['a']
。 - 字符
'b'
:压入栈中,栈内容:['a', 'b']
。 - 字符
'b'
:与栈顶字符'b'
匹配,移除栈顶字符,栈内容:['a']
。 - 字符
'a'
:与栈顶字符'a'
匹配,移除栈顶字符,栈内容:[]
。
- 字符
- 结果:
stack.size() = 0
(所有字符匹配成功)。
示例 2:s = “abc”
- 遍历过程:
- 字符
'a'
:压入栈中,栈内容:['a']
。 - 字符
'b'
:压入栈中,栈内容:['a', 'b']
。 - 字符
'c'
:压入栈中,栈内容:['a', 'b', 'c']
。
- 字符
- 结果:
stack.size() = 3
(所有字符未匹配)。
示例 3:s = “aabbcc”
- 遍历过程:
- 字符
'a'
:压入栈中,栈内容:['a']
。 - 字符
'a'
:与栈顶字符'a'
匹配,移除栈顶字符,栈内容:[]
。 - 字符
'b'
:压入栈中,栈内容:['b']
。 - 字符
'b'
:与栈顶字符'b'
匹配,移除栈顶字符,栈内容:[]
。 - 字符
'c'
:压入栈中,栈内容:['c']
。 - 字符
'c'
:与栈顶字符'c'
匹配,移除栈顶字符,栈内容:[]
。
- 字符
- 结果:
stack.size() = 0
(所有字符匹配成功)。
总结
- 功能:统计字符串中未匹配字符的数量。
- 核心逻辑:
- 使用栈来匹配相邻的相同字符。
- 如果字符匹配成功,移除栈顶字符;否则,将字符压入栈中。
- 最终返回栈中剩余的未匹配字符数量。
- 适用场景:需要检查字符串中是否存在未匹配的字符。
- 注意事项:
- 输入字符串只能包含字母(
A-Z
或a-z
)。 - 如果字符串为空,结果为
0
。
- 输入字符串只能包含字母(
如果有其他问题,欢迎随时提问!