如果你熟悉 Shell 编程,那么一定了解过花括号展开,它可以用来生成任意字符串。
花括号展开的表达式可以看作一个由 花括号、逗号 和 小写英文字母 组成的字符串,定义下面几条语法规则:
- 如果只给出单一的元素
x
,那么表达式表示的字符串就只有"x"
。R(x) = {x}
<ul> <li>例如,表达式 <code>"a"</code> 表示字符串 <code>"a"</code>。</li> <li>而表达式 <code>"w"</code> 就表示字符串 <code>"w"</code>。</li> </ul> </li> <li>当两个或多个表达式并列,以逗号分隔,我们取这些表达式中元素的并集。<code>R({e_1,e_2,...}) = R(e_1) ∪ R(e_2) ∪ ...</code> <ul> <li>例如,表达式 <code>"{a,b,c}"</code> 表示字符串 <code>"a","b","c"</code>。</li> <li>而表达式 <code>"{{a,b},{b,c}}"</code> 也可以表示字符串 <code>"a","b","c"</code>。</li> </ul> </li> <li>要是两个或多个表达式相接,中间没有隔开时,我们从这些表达式中各取一个元素依次连接形成字符串。<code>R(e_1 + e_2) = {a + b for (a, b) in R(e_1) × R(e_2)}</code> <ul> <li>例如,表达式 <code>"{a,b}{c,d}"</code> 表示字符串 <code>"ac","ad","bc","bd"</code>。</li> </ul> </li> <li>表达式之间允许嵌套,单一元素与表达式的连接也是允许的。 <ul> <li>例如,表达式 <code>"a{b,c,d}"</code> 表示字符串 <code>"ab","ac","ad"</code>。</li> <li>例如,表达式 <code>"a{b,c}{d,e}f{g,h}"</code> 可以表示字符串 <code>"abdfg", "abdfh", "abefg", "abefh", "acdfg", "acdfh", "acefg", "acefh"</code>。</li> </ul> </li>
给出表示基于给定语法规则的表达式 expression
,返回它所表示的所有字符串组成的有序列表。
假如你希望以「集合」的概念了解此题,也可以通过点击 “显示英文描述” 获取详情。
示例 1:
输入:expression = "{a,b}{c,{d,e}}" 输出:["ac","ad","ae","bc","bd","be"]
示例 2:
输入:expression = "{{a,z},a{b,c},{ab,z}}" 输出:["a","ab","ac","z"] 解释:输出中 不应 出现重复的组合结果。
提示:
1 <= expression.length <= 60
expression[i]
由'{'
,'}'
,','
或小写英文字母组成- 给出的表达式
expression
用以表示一组基于题目描述中语法构造的字符串
方法一:递归
设计递归函数 dfs(exp)
:
- 如果
exp
不包含{}
,将exp
中的字符加入结果集s
中,返回; - 否则,找到第一个
}
的位置$j$ ,从$j$ 往前找到第一个{
的位置$i$ ,将$exp[i+1..j-1]$ 之间的字符串按照,
分割,得到一个字符串数组bs
。将exp[0..i-1]
和exp[j+1..]
作为前缀$a$ 和后缀$c$ ,分别与bs
中的每个字符串$b$ 拼接,然后递归调用dfs(a+b+c)
。
最后对结果集排序,返回。
class Solution:
def braceExpansionII(self, expression: str) -> List[str]:
def dfs(exp):
j = exp.find('}')
if j == -1:
s.add(exp)
return
i = j
while exp[i] != '{':
i -= 1
a, c, = exp[:i], exp[j + 1:]
for b in exp[i + 1: j].split(','):
dfs(a + b + c)
s = set()
dfs(expression)
return sorted(s)
class Solution {
private TreeSet<String> s = new TreeSet<>();
public List<String> braceExpansionII(String expression) {
dfs(expression);
return new ArrayList<>(s);
}
private void dfs(String exp) {
int j = exp.indexOf('}');
if (j == -1) {
s.add(exp);
return;
}
int i = j;
while (exp.charAt(i) != '{') {
--i;
}
String a = exp.substring(0, i);
String c = exp.substring(j + 1);
for (String b : exp.substring(i + 1, j).split(",")) {
dfs(a + b + c);
}
}
}
class Solution {
public:
set<string> s;
vector<string> braceExpansionII(string expression) {
dfs(expression);
return vector<string>(s.begin(), s.end());
}
void dfs(string exp) {
int j = exp.find('}');
if (j == -1) {
s.insert(exp);
return;
}
int i = j;
while (exp[i] != '{') {
--i;
}
string a = exp.substr(0, i);
string c = exp.substr(j + 1);
stringstream ss(exp.substr(i + 1, j - i - 1));
string b;
while (getline(ss, b, ',')) {
dfs(a + b + c);
}
}
};
func braceExpansionII(expression string) []string {
s := map[string]struct{}{}
var dfs func(exp string)
dfs = func(exp string) {
j := strings.IndexByte(exp, '}')
if j == -1 {
s[exp] = struct{}{}
return
}
i := j
for exp[i] != '{' {
i--
}
a, c := exp[:i], exp[j+1:]
for _, b := range strings.Split(exp[i+1:j], ",") {
dfs(a + b + c)
}
}
dfs(expression)
ans := []string{}
for v := range s {
ans = append(ans, v)
}
sort.Strings(ans)
return ans
}