题目地址:
https://leetcode.com/problems/brace-expansion/
给定一个字符串
s
s
s,其中含有类似于{a,b}
这样的括号,它可以代表括号中任意其中一个字符。题目保证括号最多一层。
s
s
s就是由若干字符串和含若干字符的括号拼接而成。问其将括号展开后能得到的所有字符串。例如,"{a,b}c{d,e}f"
展开可以得到["acdf","acef","bcdf","bcef"]
。要求返回的结果按字典序排序。
思路是DFS。先构造一个list of list,每个list都存了可以供选择的字符,例如上面的例子,最后构造出来的就是[[a,b], [c], [d,e]]
,然后直接DFS枚举即可。注意,每个内层的list需要按字典序排好序,枚举的时候每个list从左向右枚举,这样得到的字符串就是按字典序加入最终结果的。代码如下:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Solution {
public String[] expand(String S) {
List<String> ans = new ArrayList<>();
List<List<Character>> lists = new ArrayList<>();
for (int i = 0, j = 0; i < S.length(); i++) {
// 遇到单个字符,直接加入
if (S.charAt(i) != '{') {
lists.add(new ArrayList<>(Arrays.asList(S.charAt(i))));
} else {
// 否则解析出花括号里的字符串
j = i;
while (j < S.length() && S.charAt(j) != '}') {
j++;
}
String sub = S.substring(i + 1, j);
// 按逗号分开,得到每个单个字符
String[] ss = sub.split(",");
List<Character> list = new ArrayList<>();
for (String s : ss) {
list.add(s.charAt(0));
}
// 加入后排个序
list.sort((c1, c2) -> Character.compare(c1, c2));
lists.add(list);
// 将i挪到后面
i = j;
}
}
dfs(0, new StringBuilder(), lists, ans);
String[] res = new String[ans.size()];
for (int i = 0; i < res.length; i++) {
res[i] = ans.get(i);
}
return res;
}
private void dfs(int idx, StringBuilder sb, List<List<Character>> lists, List<String> res) {
// 所有list都枚举完了,则加入res
if (idx == lists.size()) {
res.add(sb.toString());
return;
}
// 否则枚举下标为idx的list的每个字符,加入sb
for (int i = 0; i < lists.get(idx).size(); i++) {
sb.append(lists.get(idx).get(i));
dfs(idx + 1, sb, lists, res);
sb.setLength(sb.length() - 1);
}
}
}
时间复杂度需要看具体字符串是怎样的,如果括号非常多并且括号里的字符也非常多,则是指数级的。空间 O ( n ) O(n) O(n)。