Medium
题目描述
给定一个字符串数组 words,由不同的 4 个字母组成的字符串组成,每个字符串只包含小写英文字母。
一个单词方格由 4 个不同的单词组成:top、left、right 和 bottom,排列如下:
- top 构成顶行
- bottom 构成底行
- left 构成左列(从上到下)
- right 构成右列(从上到下)
必须满足以下条件:
top[0] == left[0],top[3] == right[0]bottom[0] == left[3],bottom[3] == right[3]
返回所有有效的不同单词方格,按 4 元组 (top, left, right, bottom) 的字典序升序排列。
示例 1:
输入: words = ["able","area","echo","also"]
输出: [["able","area","echo","also"],["area","able","also","echo"]]
示例 2:
输入: words = ["code","cafe","eden","edge"]
输出: []
约束:
4 <= words.length <= 15words[i].length == 4words[i]只包含小写英文字母- 所有
words[i]都不同
解题思路
这道题需要找出所有满足条件的 4 个单词组成的方格。根据题目描述,我们需要找到 4 个不同的单词作为 top、left、right、bottom,使得四个角的字符满足约束条件。
思路分析:
- 暴力枚举:由于单词数量最多 15 个,我们可以使用四层循环枚举所有可能的 4 个单词组合
- 约束检查:对于每个组合,检查是否满足四个角的约束条件
- 去重和排序:使用 set 去重,最后转换为排序的结果
具体步骤:
- 枚举所有可能的 (top, left, right, bottom) 组合
- 检查约束条件:
top[0] == left[0]、top[3] == right[0]、bottom[0] == left[3]、bottom[3] == right[3] - 将满足条件的组合加入结果集
- 由于要求字典序排序,我们可以使用 set 自动排序并去重
时间复杂度为 O(n⁴),其中 n 是单词数量。虽然看起来复杂度较高,但由于 n ≤ 15,实际运行时间是可接受的。
代码实现
class Solution {
public:
vector<vector<string>> wordSquares(vector<string>& words) {
set<vector<string>> result;
int n = words.size();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) continue;
for (int k = 0; k < n; k++) {
if (k == i || k == j) continue;
for (int l = 0; l < n; l++) {
if (l == i || l == j || l == k) continue;
string top = words[i];
string left = words[j];
string right = words[k];
string bottom = words[l];
if (top[0] == left[0] && top[3] == right[0] &&
bottom[0] == left[3] && bottom[3] == right[3]) {
result.insert({top, left, right, bottom});
}
}
}
}
}
return vector<vector<string>>(result.begin(), result.end());
}
};
class Solution:
def wordSquares(self, words: List[str]) -> List[List[str]]:
result = set()
n = len(words)
for i in range(n):
for j in range(n):
if i == j:
continue
for k in range(n):
if k == i or k == j:
continue
for l in range(n):
if l == i or l == j or l == k:
continue
top, left, right, bottom = words[i], words[j], words[k], words[l]
if (top[0] == left[0] and top[3] == right[0] and
bottom[0] == left[3] and bottom[3] == right[3]):
result.add((top, left, right, bottom))
return sorted(list(result))
public class Solution {
public IList<IList<string>> WordSquares(string[] words) {
var result = new SortedSet<string>(StringComparer.Ordinal);
int n = words.Length;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j) continue;
for (int k = 0; k < n; k++) {
if (k == i || k == j) continue;
for (int l = 0; l < n; l++) {
if (l == i || l == j || l == k) continue;
string top = words[i];
string left = words[j];
string right = words[k];
string bottom = words[l];
if (top[0] == left[0] && top[3] == right[0] &&
bottom[0] == left[3] && bottom[3] == right[3]) {
string key = $"{top},{left},{right},{bottom}";
result.Add(key);
}
}
}
}
}
var finalResult = new List<IList<string>>();
foreach (string s in result) {
var parts = s.Split(',');
finalResult.Add(new List<string> { parts[0], parts[1], parts[2], parts[3] });
}
return finalResult;
}
}
var wordSquares = function(words) {
const result = [];
const n = words.length;
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
if (i === j) continue;
for (let k = 0; k < n; k++) {
if (k === i || k === j) continue;
for (let l = 0; l < n; l++) {
if (l === i || l === j || l === k) continue;
const top = words[i];
const left = words[j];
const right = words[k];
const bottom = words[l];
if (top[0] === left[0] &&
top[3] === right[0] &&
bottom[0] === left[3] &&
bottom[3] === right[3]) {
result.push([top, left, right, bottom]);
}
}
}
}
}
result.sort((a, b) => {
for (let i = 0; i < 4; i++) {
if (a[i] < b[i]) return -1;
if (a[i] > b[i]) return 1;
}
return 0;
});
return result;
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n⁴) | 四层循环遍历所有可能的单词组合,每次检查约束条件为 O(1) |
| 空间复杂度 | O(k) | k 为满足条件的方格数量,用于存储结果 |