给定一份单词的清单,设计一个算法,创建由字母组成的面积最大的矩形,其中每一行组成一个单词(自左向右),每一列也组成一个单词(自上而下)。不要求这些单词在清单里连续出现,但要求所有行等长,所有列等高。
如果有多个面积最大的矩形,输出任意一个均可。一个单词可以重复使用。
示例 1:
输入: [“this”, “real”, “hard”, “trh”, “hea”, “iar”, “sld”]
输出:
[
“this”,
“real”,
“hard”
]
示例 2:
输入: [“aa”]
输出: [“aa”,“aa”]
java代码:
class Solution {
class Trie {
Trie[] childs;
boolean isleaf;
public Trie() {
isleaf = false;
childs = new Trie[26];
}
}
private Trie root;
private List<String> ans;
private int maxArea, maxLength;
private Map<Integer, Set<String>> map;
public String[] maxRectangle(String[] words) {
build(words);
map = new HashMap<>();
maxArea = maxLength = 0;
ans = new ArrayList<>();
for (String s : words) {
int len = s.length();
maxLength = Math.max(maxLength, len);
Set<String> st = map.getOrDefault(len, new HashSet<>());
st.add(s);
map.put(len, st);
}
List<String> path = new ArrayList<>();
for (int key : map.keySet()) {
path.clear();
dfs(map.get(key), path, key);
}
int size = ans.size();
String[] results = new String[size];
for (int i = 0; i < size; i++)
results[i] = ans.get(i);
return results;
}
private void build(String[] s) {
root = new Trie();
for (String str : s) {
Trie node = root;
for (char c : str.toCharArray()) {
int t = c - 'a';
if (node.childs[t] == null)
node.childs[t] = new Trie();
node = node.childs[t];
}
node.isleaf = true;
}
}
private void dfs(Set<String> st, List<String> path, int len) {
if (len * maxLength <= maxArea) return;
if (path.size() > maxLength) return;
for (String str : st) {
path.add(str);
boolean[] res = isValid(path);
if (res[0]) {
int area = path.size() * path.get(0).length();
if (res[1] && area > maxArea) {
maxArea = area;
ans = new ArrayList<>(path);
}
dfs(st, path, len);
}
path.remove(path.size() - 1);
}
}
private boolean[] isValid(List<String> list) {
boolean allLeaf = true;
int m = list.size();
int n = list.get(0).length();
for (int i = 0; i < n; i++) {
Trie node = root;
for (int j = 0; j < m; j++) {
int t = list.get(j).charAt(i) - 'a';
if (node.childs[t] == null)
return new boolean[]{false, false};
node = node.childs[t];
}
if (!node.isleaf)
allLeaf = false;
}
return new boolean[]{true, allLeaf};
}
}