精品推荐:
《征服数据结构》,《经典图论算法》
在牛客网上看到一个帖子,一网友说之前已经签了一家公司,现在又找了一家公司,并且这家公司也发了offer,让他和上一家公司解约。结果他和上一家公司解约完之后,这家公司发现他是专升本的,又把offer给撤回了,挺无语的。
网友评论:
--------------下面是今天的算法题--------------
来看下今天的算法题,这题是LeetCode的第17:电话号码的字母组合。这题昨天我们刚讲过,因为这题有两种常见的解决思路,一种是DFS,一种是BFS,我们昨天讲的是DFS,今天讲下使用BFS怎么实现。
问题描述
来源:LeetCode第17题
难度:中等
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按任意顺序返回。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例1:
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
字符串中的字符
问题分析
昨天我们讲这题《电话号码的字母组合》使用的是DFS,把它的实现过程看作是一棵树,如下图所示。
我们知道树的遍历除了DFS以外还可以使用BFS,树的BFS遍历就是一层一层的遍历,一般都会配合着队列来使用,如下图所示。
实际上这题给的并不是一棵树,这棵树只是我们想象的,那我们怎么确定遍历到叶子节点了呢,实际上很简单,如果有 n 个数字,那么叶子节点字符串的长度就应该是 n 。
JAVA:
public List<String> letterCombinations(String digits) {
LinkedList<String> ans = new LinkedList<>();
if (digits == null || digits.isEmpty())
return ans;
String[] refs = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
ans.add("");// 根节点是空的,入队。
while (ans.peek().length() != digits.length()) {
String remove = ans.poll();// 出队
String ref = refs[digits.charAt(remove.length()) - '0'];// 根据数字查找对应字符串。
// 相当于把当前节点的所有子节点入队。
for (int i = 0; i < ref.length(); i++) {
ans.add(remove + ref.charAt(i));// 入队
}
}
return ans;
}
C++:
public:
vector<string> letterCombinations(string digits) {
if (digits.empty())
return {};
queue<string> q;// 队列
string refs[] = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
q.emplace("");// 根节点是空的,入队。
while (q.front().length() != digits.length()) {
string remove = q.front();
q.pop();// 出队
// 取出数字对应的字符串,用remove与该字符串的每一个字符组合。
string ref = refs[digits[remove.length()] - '0'];
for (int i = 0; i < ref.length(); i++)
q.push(remove + ref[i]);// 入队
}
// 把队列转vector。
vector<string> v;
while (!q.empty()) {
v.push_back(q.front());
q.pop();
}
return v;
}
C:
char **letterCombinations(char *digits, int *returnSize) {
*returnSize = 0;
char **ans = malloc(150 * sizeof(char *));
if (strlen(digits) == 0)
return ans;
char **q = malloc(300 * sizeof(char *));// 队列
int left = 0, right = 0;// 队列的范围,左闭右开
char refs[][5] = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
q[right++] = calloc(1, sizeof(char));// 空字符串
while (strlen(q[left]) != strlen(digits)) {
char *remove = q[left++];// 出队
// 取出数字对应的字符串,用remove与该字符串的每一个字符组合。
char *ref = refs[digits[strlen(remove)] - '0'];
for (int i = 0; i < strlen(ref); i++) {
q[right] = calloc(5, sizeof(char));
strcpy(q[right], remove);
q[right][strlen(remove)] = ref[i];
right++;
}
}
for (int i = left; i < right; ++i) {
ans[*returnSize] = malloc(strlen(q[i]) + 1);
strcpy(ans[(*returnSize)++], q[i]);
}
// 内存释放
for (int i = 0; i < right; ++i)
free(q[i]);
free(q);
return ans;
}
Python:
def letterCombinations(self, digits: str) -> List[str]:
if not digits:
return []
d = deque()
refs = ["", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"]
d.append("") # 根节点是空的,入队。
# 比如abc和def,先把abc个字符入队,然后再分别出队和def各字符组合。
while len(d[0]) != len(digits):
remove = d.popleft() # 出队
# 取出数字对应的字符串,用remove与该字符串的每一个字符组合。
ref = refs[ord(digits[len(remove)]) - ord('0')]
for i in range(0, len(ref)):
d.append(remove + ref[i])
return list(d)
笔者简介
博哥,真名:王一博,毕业十多年,《算法秘籍》作者,专注于数据结构和算法的讲解,在全球30多个算法网站中累计做题2000多道,在公众号中写算法题解800多题,对算法题有自己独特的解题思路和解题技巧,喜欢的可以给个关注,也可以下载我整理的1000多页的PDF算法文档。
《征服数据结构》目录
《经典图论算法》目录
我的新书《算法秘籍》出版了。