问题
题目描述
在某个字符串(长度不超过 100)中有左括号、右括号和大小写字母;规定(与常见的算数式子一样)任何一个左括号都从内到外与在它右边且距离最近的右括号匹配。写一个程序,找到无法匹配的左括号和右括号,输出原来的字符串,并在下一行标出不能匹配的括号。不能匹配的左括号用"$"标注,不能匹配的右括号用"?"标注。
输入
输入包括多组数据,每组数据一行,包含一个字符串,只包含左右括号和大小写字母,字符串长度不超过 100。
输出
对每组输出数据,输出两行,第一行包含原始输入字符,第二行由"$""?"和空格组成,"$"和"?"表示与之对应的左括号和右括号不能匹配。
样例输入
)(rttyy())sss)(
样例输出
)(rttyy())sss)(
? ?$
代码
思路:每个右括号必定要与之前未被匹配的左括号中最靠右的一个进行匹配。因此,可以从左至右的顺序遍历整个字符串,遍历过程中遇到左括号,就将其放入栈中以等待后续右括号的匹配;遇到右括号,若此时栈非空,则栈顶左括号必定和当前右括号匹配;相反若此时栈为空,则表示当前右括号不存在与之匹配的左括号,右括号匹配失败;当字符串全部遍历完后,若栈非空,则表明栈中的左括号不存在与之匹配的右括号,左括号匹配失败。
Java代码
import java.util.Scanner;
import java.util.Stack;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()){
String str = scanner.nextLine();
Stack<Character> stack = new Stack<>(); //该栈用以判断括号的配对情况
Stack<Integer> flag = new Stack<>(); //该栈用于记录没有被匹配的左括号下标位置
char[] cStr = new char[str.length()]; //用一个数组来记录?、$和空格
for(int i = 0;i < str.length();i++){
char ch = str.charAt(i);
if(ch == '('){
stack.push(ch);
cStr[i] = '$';
flag.push(i);
} else if (ch == ')') {
if(!stack.isEmpty() && stack.peek() == '('){
stack.pop();
cStr[i] = ' ';
cStr[flag.pop()] = ' ';
}else {
stack.push(ch);
cStr[i] = '?';
}
}else {
cStr[i] = ' ';
}
}
System.out.println(str);
for(int i = 0;i < str.length();i++){
System.out.print(cStr[i]);
}
}
}
}
C+STL代码
C版本的代码比Java更加简化,将判断括号情况的栈和存储未匹配的左括号下标的栈合为一个(右括号未匹配直接在字符串中进行修改)
// 括号匹配问题
//
#include <iostream>
#include <cstdio>
#include <string>
#include <stack>
using namespace std;
int main(){
string str;
while(cin >> str){
int length = str.size();
stack<int> stack; //用以记录未匹配的左括号所对应的下标
string answer(length,' '); //如果这一步不进行初始化,就会打印错误,导致打印数字的现象发生
for (int i = 0; i < length; i++) {
char ch = str[i];
if(ch == '('){
answer[i] = '$';
stack.push(i);
}else if (ch == ')'){
if(!stack.empty()){
answer[stack.top()] = ' ';
stack.pop();
}else{
answer[i] = '?';
}
}
}
cout << str << endl;
cout << answer << endl;
}
}