本文不是对正则表达式的规范描述,只是对结合题目对正则表达式的一点使用。无需了解的请跳过本文
1.题目
思路: 思路:1.建立两个栈:数栈和符号栈。2.扫描,遇到数则进数栈,遇到符号[则入栈,遇到字符串则入符号栈,当遇到]时候,从符号栈中弹出字符串直到[或栈空为止,并从数栈弹出栈顶,组成字符串对应倍数的新字符串,并压入字符栈,直到扫描结束
代码部分:
class Solution {
public String decodeString(String s) {
// 思路:建立两个栈:数栈和符号栈。
// 扫描,遇到数则进数栈
// 扫描,遇到符号[则入栈,遇到字母则如符号栈,当遇到]时候,从符号栈中弹出字符串直到[或栈空为止,并从数栈弹出栈顶,组成
// 字符串对应倍数的新字符串,并压入字符栈,直到扫描结束
LinkedList<String> stackStr = new LinkedList();
LinkedList<Integer> stackNum = new LinkedList();
// 对s做处理,否则会出现100[ab]但是只能单个字符1,0,0入数字栈等等诸多意外的情况
String[] splitStr = s.split("(?<=\\[)(?=\\d|\\D)|(?<=\\])(?=\\d|\\D)|(?<=\\d)(?=\\D)|(?<=\\D)(?=\\])|(?<=\\D)(?=\\d)");
for (int i = 0; i < splitStr.length; i++) {
String temp = splitStr[i];
if (temp.equals("[") || temp.matches("[a-z]+")) {
stackStr.push(temp);// 字母和左括号
} else if (temp.equals("]")) {// 右括号
// 如果为]则弹出字符直到[为止和 数一起做处理
String createStr = "";
while (!stackStr.isEmpty() && !stackStr.peek().equals("[")) {
createStr = stackStr.pop() + createStr;
}
}
stackStr.pop();// 弹出[
int b = stackNum.pop();
String res = ac(createStr, b);
stackStr.push(res);
} else {// 数字部分处理
stackNum.push(Integer.parseInt(temp));
}
}
// 如过栈中有数值,则进行处理拼凑后弹出
if (!stackNum.isEmpty()) {
return ac(stackStr.pop(), stackNum.pop());
} else {
// 按照顺序弹出所有字符串
String result = "";
while (!stackStr.isEmpty()) {
result = stackStr.pop() + result;
}
return result;
}
}
//字符串与数字进行倍数处理
public String ac(String str, int b) {
String nstr = "";
for (int i = 0; i < b; i++) {
nstr = nstr + str;
}
return nstr;
}
}
接下来重点解释下代码中用到的正则表达式
前提:注意不同语言的正则表达式处理是有区别的
所以各位看到其他语言的符合自己想要功能的正则表达式,请不要随意拷贝,否则很可能出现错误
正则表达式
1.正则表达式中的转义字符
在正则表达式中,.,^,$,[,],\
等都有特定的含义。如果在正则表达式中想与这些字符本身进行匹配的的,需要在这些元字符前加上\对其进行转义。
(?<=\D)(?=\d)
- 匹配非数字(\D
)和数字(\d
)之间的位置(?<=\d)(?=\D)
- 匹配数字和非数字之间的位置。- 需要转义字符\(有些语言对于转义字符处理和java的不同)
\[
表示匹配[符号,同理可得\]
等
\d和\D的含义
\d | 数字字符匹配。等效于 [0-9]。 |
---|---|
\D | 非数字字符匹配。等效于[^0-9] 。 |
同理可得\[和\] 等就是匹配[ ]等符号 |
(?<=\\[)(?=\\d|\\D)|(?<=\\])(?=\\d|\\D)|(?<=\\d)(?=\\D)|(?<=\\D)(?=\\])|(?<=\\D)(?=\\d)
表达意思分别是:
1.匹配[到(数字与非数字)之间的位置,即[符号 (?<=\\[)(?=\\d|\\D)
2.匹配]到(数字与非数字)之间的位置,即]符号 (?<=\\])(?=\\d|\\D)
3.匹配数字到非数字之间的位置,即获取数字部分: (?<=\\d)(?=\\D) 例如:2[be],需要将2和[拆开
4.匹配非数字到]之间的位置 ,即获取]之前的字母部分 (?<=\\D)(?=\\]) 例如:[be] ,由于1,可以拆开[符号,由于4,可以拆开be,由于2,可以获取]
5.匹配非数字到数字的部分 (?<=\\D)(?=\\d) 例如:对于3[a2[be]],这里就有a2,需要拆开a和2 (?<=\\d)(?=\\D)
具体例子:
1.匹配数字,直到遇到非数字
2.匹配右边部分包括 [ 的内容,直到遇到非数字或数字部分
3.匹配左边部分包括 ] 的内容,直到遇到非数字或数字部分
4.左边匹配非数部分,直到遇到]
5.左边匹配到非数字,直到遇到数字的部分
对于以上1-5进行或|运算,即满足一个就要拆分
言归正传
题解效率很低,可以进行优化,例如使用StringBuilder等,或者采取官方题解的递归等思路进行
本题目用该方法只是因为想用正则,但是题解的正则基本都是python和JavaScript。