Skip to content

Commit 0cf8c9c

Browse files
authoredJul 29, 2023
feat: add solutions to lcci problem: No.17.25 (#1338)
No.17.25.Word Rectangle
1 parent e24dba2 commit 0cf8c9c

File tree

6 files changed

+926
-0
lines changed

6 files changed

+926
-0
lines changed
 

‎lcci/17.25.Word Rectangle/README.md

+318
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
## 题目描述
66

77
<!-- 这里写题目描述 -->
8+
89
<p>给定一份单词的清单,设计一个算法,创建由字母组成的面积最大的矩形,其中每一行组成一个单词(自左向右),每一列也组成一个单词(自上而下)。不要求这些单词在清单里连续出现,但要求所有行等长,所有列等高。</p>
910
<p>如果有多个面积最大的矩形,输出任意一个均可。一个单词可以重复使用。</p>
1011
<p><strong>示例 1:</strong></p>
@@ -28,22 +29,339 @@
2829
## 解法
2930

3031
<!-- 这里可写通用的实现逻辑 -->
32+
33+
**方法一:分组 + 回溯 + 字典树**
34+
35+
我们注意到,构建单词矩阵时所用的单词长度是相同的,因此,我们可以将单词按照长度分组,记录在哈希表 $d$ 中。对于每个长度,我们只需要考虑该长度的单词即可。
36+
37+
我们使用回溯的方法来构建单词矩阵。我们使用一个列表 $t$ 来记录当前已经构建好的单词矩阵,列表中的每个单词都具有相同的长度。我们从哈希表 $d$ 中取出长度为 $n$ 的单词列表,从中选择一个单词 $w$,加入到 $t$ 中。如果此时不是一个合法的单词矩阵,那么我们就不继续往下搜索,而是尝试选择另一个单词。如果是一个合法的单词矩阵,并且已经构建完成,那么我们更新最大面积以及答案矩阵;然后,我们递归地进行搜索,寻找下一个单词。最后,我们将 $w$ 从 $t$ 中移除,进入下一轮搜索。
38+
39+
在判断单词矩阵是否合法时,我们可以使用字典树来进行优化。我们将所有的单词加入到字典树中,然后对于每一列,我们检查其是否是一个单词。如果是一个单词,那么我们就检查下一列,否则我们就可以停止对该单词矩阵的搜索了。
40+
3141
<!-- tabs:start -->
3242

3343
### **Python3**
3444

3545
<!-- 这里可写当前语言的特殊实现逻辑 -->
3646

3747
```python
48+
class Trie:
49+
def __init__(self):
50+
self.children = [None] * 26
51+
self.is_end = False
52+
53+
def insert(self, w):
54+
node = self
55+
for c in w:
56+
idx = ord(c) - ord("a")
57+
if node.children[idx] is None:
58+
node.children[idx] = Trie()
59+
node = node.children[idx]
60+
node.is_end = True
61+
3862

63+
class Solution:
64+
def maxRectangle(self, words: List[str]) -> List[str]:
65+
def check(mat):
66+
m, n = len(mat), len(mat[0])
67+
ans = 1
68+
for j in range(n):
69+
node = trie
70+
for i in range(m):
71+
idx = ord(mat[i][j]) - ord("a")
72+
if node.children[idx] is None:
73+
return 0
74+
node = node.children[idx]
75+
if not node.is_end:
76+
ans = 2
77+
return ans
78+
79+
def dfs(ws):
80+
nonlocal ans, max_s, max_l
81+
if len(ws[0]) * max_l <= max_s or len(t) >= max_l:
82+
return
83+
84+
for w in ws:
85+
t.append(w)
86+
st = check(t)
87+
if st == 0:
88+
t.pop()
89+
continue
90+
if st == 1 and max_s < len(t) * len(t[0]):
91+
ans = t[:]
92+
max_s = len(t) * len(t[0])
93+
dfs(ws)
94+
t.pop()
95+
96+
d = defaultdict(list)
97+
trie = Trie()
98+
max_l = 0
99+
for w in words:
100+
trie.insert(w)
101+
max_l = max(max_l, len(w))
102+
d[len(w)].append(w)
103+
104+
max_s = 0
105+
ans = []
106+
for ws in d.values():
107+
t = []
108+
dfs(ws)
109+
return ans
39110
```
40111

41112
### **Java**
42113

43114
<!-- 这里可写当前语言的特殊实现逻辑 -->
44115

45116
```java
117+
class Trie {
118+
Trie[] children = new Trie[26];
119+
boolean isEnd;
120+
121+
void insert(String word) {
122+
Trie node = this;
123+
for (char c : word.toCharArray()) {
124+
c -= 'a';
125+
if (node.children[c] == null) {
126+
node.children[c] = new Trie();
127+
}
128+
node = node.children[c];
129+
}
130+
node.isEnd = true;
131+
}
132+
}
133+
134+
class Solution {
135+
private int maxL;
136+
private int maxS;
137+
private String[] ans;
138+
private Trie trie = new Trie();
139+
private List<String> t = new ArrayList<>();
140+
141+
public String[] maxRectangle(String[] words) {
142+
Map<Integer, List<String>> d = new HashMap<>(100);
143+
for (String w : words) {
144+
maxL = Math.max(maxL, w.length());
145+
trie.insert(w);
146+
d.computeIfAbsent(w.length(), k -> new ArrayList<>()).add(w);
147+
}
148+
for (List<String> ws : d.values()) {
149+
t.clear();
150+
dfs(ws);
151+
}
152+
return ans;
153+
}
154+
155+
private void dfs(List<String> ws) {
156+
if (ws.get(0).length() * maxL <= maxS || t.size() >= maxL) {
157+
return;
158+
}
159+
for (String w : ws) {
160+
t.add(w);
161+
int st = check(t);
162+
if (st == 0) {
163+
t.remove(t.size() - 1);
164+
continue;
165+
}
166+
if (st == 1 && maxS < t.size() * t.get(0).length()) {
167+
maxS = t.size() * t.get(0).length();
168+
ans = t.toArray(new String[0]);
169+
}
170+
dfs(ws);
171+
t.remove(t.size() - 1);
172+
}
173+
}
174+
175+
private int check(List<String> mat) {
176+
int m = mat.size(), n = mat.get(0).length();
177+
int ans = 1;
178+
for (int j = 0; j < n; ++j) {
179+
Trie node = trie;
180+
for (int i = 0; i < m; ++i) {
181+
int idx = mat.get(i).charAt(j) - 'a';
182+
if (node.children[idx] == null) {
183+
return 0;
184+
}
185+
node = node.children[idx];
186+
}
187+
if (!node.isEnd) {
188+
ans = 2;
189+
}
190+
}
191+
return ans;
192+
}
193+
}
194+
```
195+
196+
### **C++**
197+
198+
```cpp
199+
class Trie {
200+
public:
201+
vector<Trie*> children;
202+
bool is_end;
203+
204+
Trie() {
205+
children = vector<Trie*>(26, nullptr);
206+
is_end = false;
207+
}
208+
209+
void insert(const string& word) {
210+
Trie* cur = this;
211+
for (char c : word) {
212+
c -= 'a';
213+
if (cur->children[c] == nullptr) {
214+
cur->children[c] = new Trie;
215+
}
216+
cur = cur->children[c];
217+
}
218+
cur->is_end = true;
219+
}
220+
};
221+
222+
class Solution {
223+
public:
224+
vector<string> maxRectangle(vector<string>& words) {
225+
unordered_map<int, vector<string>> d;
226+
int maxL = 0, maxS = 0;
227+
vector<string> ans;
228+
vector<string> t;
229+
Trie* trie = new Trie();
230+
for (auto& w : words) {
231+
maxL = max(maxL, (int) w.size());
232+
d[w.size()].emplace_back(w);
233+
trie->insert(w);
234+
}
235+
auto check = [&](vector<string>& mat) {
236+
int m = mat.size(), n = mat[0].size();
237+
int ans = 1;
238+
for (int j = 0; j < n; ++j) {
239+
Trie* node = trie;
240+
for (int i = 0; i < m; ++i) {
241+
int idx = mat[i][j] - 'a';
242+
if (!node->children[idx]) {
243+
return 0;
244+
}
245+
node = node->children[idx];
246+
}
247+
if (!node->is_end) {
248+
ans = 2;
249+
}
250+
}
251+
return ans;
252+
};
253+
254+
function<void(vector<string>&)> dfs = [&](vector<string>& ws) {
255+
if (ws[0].size() * maxL <= maxS || t.size() >= maxL) {
256+
return;
257+
}
258+
for (auto& w : ws) {
259+
t.emplace_back(w);
260+
int st = check(t);
261+
if (st == 0) {
262+
t.pop_back();
263+
continue;
264+
}
265+
if (st == 1 && maxS < t.size() * t[0].size()) {
266+
maxS = t.size() * t[0].size();
267+
ans = t;
268+
}
269+
dfs(ws);
270+
t.pop_back();
271+
}
272+
};
273+
for (auto& [_, ws] : d) {
274+
t.clear();
275+
dfs(ws);
276+
}
277+
return ans;
278+
}
279+
};
280+
```
281+
282+
### **Go**
283+
284+
```go
285+
type Trie struct {
286+
children [26]*Trie
287+
isEnd bool
288+
}
289+
290+
func newTrie() *Trie {
291+
return &Trie{}
292+
}
293+
func (this *Trie) insert(word string) {
294+
node := this
295+
for _, c := range word {
296+
c -= 'a'
297+
if node.children[c] == nil {
298+
node.children[c] = newTrie()
299+
}
300+
node = node.children[c]
301+
}
302+
node.isEnd = true
303+
}
304+
305+
func maxRectangle(words []string) (ans []string) {
306+
trie := newTrie()
307+
d := map[int][]string{}
308+
t := []string{}
309+
var maxL, maxS int
310+
for _, w := range words {
311+
maxL = max(maxL, len(w))
312+
d[len(w)] = append(d[len(w)], w)
313+
trie.insert(w)
314+
}
315+
check := func(mat []string) int {
316+
m, n := len(mat), len(mat[0])
317+
ans := 1
318+
for j := 0; j < n; j++ {
319+
node := trie
320+
for i := 0; i < m; i++ {
321+
idx := mat[i][j] - 'a'
322+
if node.children[idx] == nil {
323+
return 0
324+
}
325+
node = node.children[idx]
326+
}
327+
if !node.isEnd {
328+
ans = 2
329+
}
330+
}
331+
return ans
332+
}
333+
var dfs func([]string)
334+
dfs = func(ws []string) {
335+
if len(ws[0])*maxL <= maxS || len(t) >= maxL {
336+
return
337+
}
338+
for _, w := range ws {
339+
t = append(t, w)
340+
st := check(t)
341+
if st == 0 {
342+
t = t[:len(t)-1]
343+
continue
344+
}
345+
if st == 1 && maxS < len(t)*len(t[0]) {
346+
maxS = len(t) * len(t[0])
347+
ans = append([]string{}, t...)
348+
}
349+
dfs(ws)
350+
t = t[:len(t)-1]
351+
}
352+
}
353+
for _, ws := range d {
354+
dfs(ws)
355+
}
356+
return
357+
}
46358
359+
func max(a, b int) int {
360+
if a > b {
361+
return a
362+
}
363+
return b
364+
}
47365
```
48366

49367
### **...**

‎lcci/17.25.Word Rectangle/README_EN.md

+308
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,321 @@
4444
### **Python3**
4545

4646
```python
47+
class Trie:
48+
def __init__(self):
49+
self.children = [None] * 26
50+
self.is_end = False
4751

52+
def insert(self, w):
53+
node = self
54+
for c in w:
55+
idx = ord(c) - ord("a")
56+
if node.children[idx] is None:
57+
node.children[idx] = Trie()
58+
node = node.children[idx]
59+
node.is_end = True
60+
61+
62+
class Solution:
63+
def maxRectangle(self, words: List[str]) -> List[str]:
64+
def check(mat):
65+
m, n = len(mat), len(mat[0])
66+
ans = 1
67+
for j in range(n):
68+
node = trie
69+
for i in range(m):
70+
idx = ord(mat[i][j]) - ord("a")
71+
if node.children[idx] is None:
72+
return 0
73+
node = node.children[idx]
74+
if not node.is_end:
75+
ans = 2
76+
return ans
77+
78+
def dfs(ws):
79+
nonlocal ans, max_s, max_l
80+
if len(ws[0]) * max_l <= max_s or len(t) >= max_l:
81+
return
82+
83+
for w in ws:
84+
t.append(w)
85+
st = check(t)
86+
if st == 0:
87+
t.pop()
88+
continue
89+
if st == 1 and max_s < len(t) * len(t[0]):
90+
ans = t[:]
91+
max_s = len(t) * len(t[0])
92+
dfs(ws)
93+
t.pop()
94+
95+
d = defaultdict(list)
96+
trie = Trie()
97+
max_l = 0
98+
for w in words:
99+
trie.insert(w)
100+
max_l = max(max_l, len(w))
101+
d[len(w)].append(w)
102+
103+
max_s = 0
104+
ans = []
105+
for ws in d.values():
106+
t = []
107+
dfs(ws)
108+
return ans
48109
```
49110

50111
### **Java**
51112

52113
```java
114+
class Trie {
115+
Trie[] children = new Trie[26];
116+
boolean isEnd;
117+
118+
void insert(String word) {
119+
Trie node = this;
120+
for (char c : word.toCharArray()) {
121+
c -= 'a';
122+
if (node.children[c] == null) {
123+
node.children[c] = new Trie();
124+
}
125+
node = node.children[c];
126+
}
127+
node.isEnd = true;
128+
}
129+
}
130+
131+
class Solution {
132+
private int maxL;
133+
private int maxS;
134+
private String[] ans;
135+
private Trie trie = new Trie();
136+
private List<String> t = new ArrayList<>();
137+
138+
public String[] maxRectangle(String[] words) {
139+
Map<Integer, List<String>> d = new HashMap<>(100);
140+
for (String w : words) {
141+
maxL = Math.max(maxL, w.length());
142+
trie.insert(w);
143+
d.computeIfAbsent(w.length(), k -> new ArrayList<>()).add(w);
144+
}
145+
for (List<String> ws : d.values()) {
146+
t.clear();
147+
dfs(ws);
148+
}
149+
return ans;
150+
}
151+
152+
private void dfs(List<String> ws) {
153+
if (ws.get(0).length() * maxL <= maxS || t.size() >= maxL) {
154+
return;
155+
}
156+
for (String w : ws) {
157+
t.add(w);
158+
int st = check(t);
159+
if (st == 0) {
160+
t.remove(t.size() - 1);
161+
continue;
162+
}
163+
if (st == 1 && maxS < t.size() * t.get(0).length()) {
164+
maxS = t.size() * t.get(0).length();
165+
ans = t.toArray(new String[0]);
166+
}
167+
dfs(ws);
168+
t.remove(t.size() - 1);
169+
}
170+
}
171+
172+
private int check(List<String> mat) {
173+
int m = mat.size(), n = mat.get(0).length();
174+
int ans = 1;
175+
for (int j = 0; j < n; ++j) {
176+
Trie node = trie;
177+
for (int i = 0; i < m; ++i) {
178+
int idx = mat.get(i).charAt(j) - 'a';
179+
if (node.children[idx] == null) {
180+
return 0;
181+
}
182+
node = node.children[idx];
183+
}
184+
if (!node.isEnd) {
185+
ans = 2;
186+
}
187+
}
188+
return ans;
189+
}
190+
}
191+
```
192+
193+
### **C++**
194+
195+
```cpp
196+
class Trie {
197+
public:
198+
vector<Trie*> children;
199+
bool is_end;
200+
201+
Trie() {
202+
children = vector<Trie*>(26, nullptr);
203+
is_end = false;
204+
}
205+
206+
void insert(const string& word) {
207+
Trie* cur = this;
208+
for (char c : word) {
209+
c -= 'a';
210+
if (cur->children[c] == nullptr) {
211+
cur->children[c] = new Trie;
212+
}
213+
cur = cur->children[c];
214+
}
215+
cur->is_end = true;
216+
}
217+
};
218+
219+
class Solution {
220+
public:
221+
vector<string> maxRectangle(vector<string>& words) {
222+
unordered_map<int, vector<string>> d;
223+
int maxL = 0, maxS = 0;
224+
vector<string> ans;
225+
vector<string> t;
226+
Trie* trie = new Trie();
227+
for (auto& w : words) {
228+
maxL = max(maxL, (int) w.size());
229+
d[w.size()].emplace_back(w);
230+
trie->insert(w);
231+
}
232+
auto check = [&](vector<string>& mat) {
233+
int m = mat.size(), n = mat[0].size();
234+
int ans = 1;
235+
for (int j = 0; j < n; ++j) {
236+
Trie* node = trie;
237+
for (int i = 0; i < m; ++i) {
238+
int idx = mat[i][j] - 'a';
239+
if (!node->children[idx]) {
240+
return 0;
241+
}
242+
node = node->children[idx];
243+
}
244+
if (!node->is_end) {
245+
ans = 2;
246+
}
247+
}
248+
return ans;
249+
};
250+
251+
function<void(vector<string>&)> dfs = [&](vector<string>& ws) {
252+
if (ws[0].size() * maxL <= maxS || t.size() >= maxL) {
253+
return;
254+
}
255+
for (auto& w : ws) {
256+
t.emplace_back(w);
257+
int st = check(t);
258+
if (st == 0) {
259+
t.pop_back();
260+
continue;
261+
}
262+
if (st == 1 && maxS < t.size() * t[0].size()) {
263+
maxS = t.size() * t[0].size();
264+
ans = t;
265+
}
266+
dfs(ws);
267+
t.pop_back();
268+
}
269+
};
270+
for (auto& [_, ws] : d) {
271+
t.clear();
272+
dfs(ws);
273+
}
274+
return ans;
275+
}
276+
};
277+
```
278+
279+
### **Go**
280+
281+
```go
282+
type Trie struct {
283+
children [26]*Trie
284+
isEnd bool
285+
}
286+
287+
func newTrie() *Trie {
288+
return &Trie{}
289+
}
290+
func (this *Trie) insert(word string) {
291+
node := this
292+
for _, c := range word {
293+
c -= 'a'
294+
if node.children[c] == nil {
295+
node.children[c] = newTrie()
296+
}
297+
node = node.children[c]
298+
}
299+
node.isEnd = true
300+
}
301+
302+
func maxRectangle(words []string) (ans []string) {
303+
trie := newTrie()
304+
d := map[int][]string{}
305+
t := []string{}
306+
var maxL, maxS int
307+
for _, w := range words {
308+
maxL = max(maxL, len(w))
309+
d[len(w)] = append(d[len(w)], w)
310+
trie.insert(w)
311+
}
312+
check := func(mat []string) int {
313+
m, n := len(mat), len(mat[0])
314+
ans := 1
315+
for j := 0; j < n; j++ {
316+
node := trie
317+
for i := 0; i < m; i++ {
318+
idx := mat[i][j] - 'a'
319+
if node.children[idx] == nil {
320+
return 0
321+
}
322+
node = node.children[idx]
323+
}
324+
if !node.isEnd {
325+
ans = 2
326+
}
327+
}
328+
return ans
329+
}
330+
var dfs func([]string)
331+
dfs = func(ws []string) {
332+
if len(ws[0])*maxL <= maxS || len(t) >= maxL {
333+
return
334+
}
335+
for _, w := range ws {
336+
t = append(t, w)
337+
st := check(t)
338+
if st == 0 {
339+
t = t[:len(t)-1]
340+
continue
341+
}
342+
if st == 1 && maxS < len(t)*len(t[0]) {
343+
maxS = len(t) * len(t[0])
344+
ans = append([]string{}, t...)
345+
}
346+
dfs(ws)
347+
t = t[:len(t)-1]
348+
}
349+
}
350+
for _, ws := range d {
351+
dfs(ws)
352+
}
353+
return
354+
}
53355
356+
func max(a, b int) int {
357+
if a > b {
358+
return a
359+
}
360+
return b
361+
}
54362
```
55363

56364
### **...**
+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
class Trie {
2+
public:
3+
vector<Trie*> children;
4+
bool is_end;
5+
6+
Trie() {
7+
children = vector<Trie*>(26, nullptr);
8+
is_end = false;
9+
}
10+
11+
void insert(const string& word) {
12+
Trie* cur = this;
13+
for (char c : word) {
14+
c -= 'a';
15+
if (cur->children[c] == nullptr) {
16+
cur->children[c] = new Trie;
17+
}
18+
cur = cur->children[c];
19+
}
20+
cur->is_end = true;
21+
}
22+
};
23+
24+
class Solution {
25+
public:
26+
vector<string> maxRectangle(vector<string>& words) {
27+
unordered_map<int, vector<string>> d;
28+
int maxL = 0, maxS = 0;
29+
vector<string> ans;
30+
vector<string> t;
31+
Trie* trie = new Trie();
32+
for (auto& w : words) {
33+
maxL = max(maxL, (int) w.size());
34+
d[w.size()].emplace_back(w);
35+
trie->insert(w);
36+
}
37+
auto check = [&](vector<string>& mat) {
38+
int m = mat.size(), n = mat[0].size();
39+
int ans = 1;
40+
for (int j = 0; j < n; ++j) {
41+
Trie* node = trie;
42+
for (int i = 0; i < m; ++i) {
43+
int idx = mat[i][j] - 'a';
44+
if (!node->children[idx]) {
45+
return 0;
46+
}
47+
node = node->children[idx];
48+
}
49+
if (!node->is_end) {
50+
ans = 2;
51+
}
52+
}
53+
return ans;
54+
};
55+
56+
function<void(vector<string>&)> dfs = [&](vector<string>& ws) {
57+
if (ws[0].size() * maxL <= maxS || t.size() >= maxL) {
58+
return;
59+
}
60+
for (auto& w : ws) {
61+
t.emplace_back(w);
62+
int st = check(t);
63+
if (st == 0) {
64+
t.pop_back();
65+
continue;
66+
}
67+
if (st == 1 && maxS < t.size() * t[0].size()) {
68+
maxS = t.size() * t[0].size();
69+
ans = t;
70+
}
71+
dfs(ws);
72+
t.pop_back();
73+
}
74+
};
75+
for (auto& [_, ws] : d) {
76+
t.clear();
77+
dfs(ws);
78+
}
79+
return ans;
80+
}
81+
};

‎lcci/17.25.Word Rectangle/Solution.go

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
type Trie struct {
2+
children [26]*Trie
3+
isEnd bool
4+
}
5+
6+
func newTrie() *Trie {
7+
return &Trie{}
8+
}
9+
func (this *Trie) insert(word string) {
10+
node := this
11+
for _, c := range word {
12+
c -= 'a'
13+
if node.children[c] == nil {
14+
node.children[c] = newTrie()
15+
}
16+
node = node.children[c]
17+
}
18+
node.isEnd = true
19+
}
20+
21+
func maxRectangle(words []string) (ans []string) {
22+
trie := newTrie()
23+
d := map[int][]string{}
24+
t := []string{}
25+
var maxL, maxS int
26+
for _, w := range words {
27+
maxL = max(maxL, len(w))
28+
d[len(w)] = append(d[len(w)], w)
29+
trie.insert(w)
30+
}
31+
check := func(mat []string) int {
32+
m, n := len(mat), len(mat[0])
33+
ans := 1
34+
for j := 0; j < n; j++ {
35+
node := trie
36+
for i := 0; i < m; i++ {
37+
idx := mat[i][j] - 'a'
38+
if node.children[idx] == nil {
39+
return 0
40+
}
41+
node = node.children[idx]
42+
}
43+
if !node.isEnd {
44+
ans = 2
45+
}
46+
}
47+
return ans
48+
}
49+
var dfs func([]string)
50+
dfs = func(ws []string) {
51+
if len(ws[0])*maxL <= maxS || len(t) >= maxL {
52+
return
53+
}
54+
for _, w := range ws {
55+
t = append(t, w)
56+
st := check(t)
57+
if st == 0 {
58+
t = t[:len(t)-1]
59+
continue
60+
}
61+
if st == 1 && maxS < len(t)*len(t[0]) {
62+
maxS = len(t) * len(t[0])
63+
ans = append([]string{}, t...)
64+
}
65+
dfs(ws)
66+
t = t[:len(t)-1]
67+
}
68+
}
69+
for _, ws := range d {
70+
dfs(ws)
71+
}
72+
return
73+
}
74+
75+
func max(a, b int) int {
76+
if a > b {
77+
return a
78+
}
79+
return b
80+
}
+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
class Trie {
2+
Trie[] children = new Trie[26];
3+
boolean isEnd;
4+
5+
void insert(String word) {
6+
Trie node = this;
7+
for (char c : word.toCharArray()) {
8+
c -= 'a';
9+
if (node.children[c] == null) {
10+
node.children[c] = new Trie();
11+
}
12+
node = node.children[c];
13+
}
14+
node.isEnd = true;
15+
}
16+
}
17+
18+
class Solution {
19+
private int maxL;
20+
private int maxS;
21+
private String[] ans;
22+
private Trie trie = new Trie();
23+
private List<String> t = new ArrayList<>();
24+
25+
public String[] maxRectangle(String[] words) {
26+
Map<Integer, List<String>> d = new HashMap<>(100);
27+
for (String w : words) {
28+
maxL = Math.max(maxL, w.length());
29+
trie.insert(w);
30+
d.computeIfAbsent(w.length(), k -> new ArrayList<>()).add(w);
31+
}
32+
for (List<String> ws : d.values()) {
33+
t.clear();
34+
dfs(ws);
35+
}
36+
return ans;
37+
}
38+
39+
private void dfs(List<String> ws) {
40+
if (ws.get(0).length() * maxL <= maxS || t.size() >= maxL) {
41+
return;
42+
}
43+
for (String w : ws) {
44+
t.add(w);
45+
int st = check(t);
46+
if (st == 0) {
47+
t.remove(t.size() - 1);
48+
continue;
49+
}
50+
if (st == 1 && maxS < t.size() * t.get(0).length()) {
51+
maxS = t.size() * t.get(0).length();
52+
ans = t.toArray(new String[0]);
53+
}
54+
dfs(ws);
55+
t.remove(t.size() - 1);
56+
}
57+
}
58+
59+
private int check(List<String> mat) {
60+
int m = mat.size(), n = mat.get(0).length();
61+
int ans = 1;
62+
for (int j = 0; j < n; ++j) {
63+
Trie node = trie;
64+
for (int i = 0; i < m; ++i) {
65+
int idx = mat.get(i).charAt(j) - 'a';
66+
if (node.children[idx] == null) {
67+
return 0;
68+
}
69+
node = node.children[idx];
70+
}
71+
if (!node.isEnd) {
72+
ans = 2;
73+
}
74+
}
75+
return ans;
76+
}
77+
}

‎lcci/17.25.Word Rectangle/Solution.py

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
class Trie:
2+
def __init__(self):
3+
self.children = [None] * 26
4+
self.is_end = False
5+
6+
def insert(self, w):
7+
node = self
8+
for c in w:
9+
idx = ord(c) - ord("a")
10+
if node.children[idx] is None:
11+
node.children[idx] = Trie()
12+
node = node.children[idx]
13+
node.is_end = True
14+
15+
16+
class Solution:
17+
def maxRectangle(self, words: List[str]) -> List[str]:
18+
def check(mat):
19+
m, n = len(mat), len(mat[0])
20+
ans = 1
21+
for j in range(n):
22+
node = trie
23+
for i in range(m):
24+
idx = ord(mat[i][j]) - ord("a")
25+
if node.children[idx] is None:
26+
return 0
27+
node = node.children[idx]
28+
if not node.is_end:
29+
ans = 2
30+
return ans
31+
32+
def dfs(ws):
33+
nonlocal ans, max_s, max_l
34+
if len(ws[0]) * max_l <= max_s or len(t) >= max_l:
35+
return
36+
37+
for w in ws:
38+
t.append(w)
39+
st = check(t)
40+
if st == 0:
41+
t.pop()
42+
continue
43+
if st == 1 and max_s < len(t) * len(t[0]):
44+
ans = t[:]
45+
max_s = len(t) * len(t[0])
46+
dfs(ws)
47+
t.pop()
48+
49+
d = defaultdict(list)
50+
trie = Trie()
51+
max_l = 0
52+
for w in words:
53+
trie.insert(w)
54+
max_l = max(max_l, len(w))
55+
d[len(w)].append(w)
56+
57+
max_s = 0
58+
ans = []
59+
for ws in d.values():
60+
t = []
61+
dfs(ws)
62+
return ans

0 commit comments

Comments
 (0)
Please sign in to comment.