LeetCode - 1684. Count the Number of Consistent Strings
在字符串处理的算法问题中,字符匹配统计是一类常见的基础问题。LeetCode第1684题 Count the Number of Consistent Strings 就属于这类问题,它考察我们如何高效地判断字符串是否符合特定的字符规则。接下来,我们将深入探讨这道题的解题思路与实现方法。
1. 题目详细解读
题目给定一个字符串 allowed
和一个字符串数组 words
。如果一个字符串的每个字符都在 allowed
中出现,那么这个字符串就被称为"一致字符串"。我们的任务是统计并返回 words
数组中一致字符串的数量。
示例
输入: allowed = "ab"
, words = ["ad", "bd", "aaab", "baa", "badab"]
输出: 2
解释: 字符串 "aaab"
和 "baa"
都是一致字符串,因为它们只包含字符 'a'
和 'b'
,而其他字符串中包含了 'd'
或 'c'
等不在 allowed
中的字符。
2. 核心解题思路
解决本题的关键在于如何高效地判断一个字符串是否为一致字符串。下面介绍两种主要的解题思路:
2.1 白名单过滤法
这种思路的核心是先将 allowed
中的字符转换为一个白名单列表,然后逐个检查每个字符串的字符是否都在这个白名单中。具体步骤如下:
- a. 构建白名单:将
allowed
字符串转换为字符列表,作为允许的字符白名单。 - b. 遍历检查:对于
words
中的每个字符串,检查其每个字符是否都存在于白名单中。 - c. 统计数量:如果一个字符串的所有字符都在白名单中,则计数器加一。
2.2 逆向排除法
这种思路则是先假设所有字符串都是一致的,然后在发现不符合条件的字符串时进行排除。具体步骤如下:
- a. 初始化计数器:将计数器初始化为
words
数组的长度,即假设所有字符串都是一致的。 - b. 遍历排除:对于每个字符串,检查其每个字符是否都存在于
allowed
中。如果发现任何一个字符不在allowed
中,则将计数器减一,并跳过当前字符串的剩余字符检查。 - c. 返回结果:最终计数器的值即为一致字符串的数量。
3. C# 代码实现(思路一)
public class Solution
{
public int CountConsistentStrings(string allowed, string[] words)
{
var allowedList = allowed.ToList();
var count = 0;
foreach (var w in words)
{
if (IsConsistent(allowedList, w))
{
count++;
}
}
return count;
}
/// <summary>
/// 判断一致字符串
/// </summary>
/// <param name="allowed">依据字符列表</param>
/// <param name="target">目标字符串</param>
/// <returns>是否为一致字符串</returns>
private bool IsConsistent(List<char> allowed, string target)
{
foreach (var c in target)
{
if (!allowed.Contains(c))
{
return false;
}
}
return true;
}
}
- 代码解析
这段C#代码实现了思路一的方法。首先,将allowed
字符串转换为字符列表allowedList
。然后遍历words
数组中的每个字符串,调用IsConsistent
方法检查是否每个字符都在allowedList
中。IsConsistent
方法通过遍历目标字符串的每个字符,使用Contains
方法检查是否存在于允许的字符列表中,如果发现任何不允许的字符则立即返回false
。
4. Python 代码实现(思路二)
class Solution:
def countConsistentStrings(self, allowed: str, words: List[str]) -> int:
count = len(words)
for w in words:
for c in w:
if allowed.find(c) == -1:
count -= 1
break
return count
- 代码解析
这段Python代码实现了思路二的方法。首先将计数器初始化为words
数组的长度。然后遍历每个字符串,对于每个字符串中的每个字符,使用find
方法检查是否存在于allowed
中。如果发现一个字符不在allowed
中,则将计数器减一,并使用break
语句跳出当前字符串的检查循环,避免不必要的检查。
5. 复杂度分析
两种思路的时间复杂度和空间复杂度基本相同:
- 时间复杂度:
O(n * m)
,其中n
是words
数组的长度,m
是每个字符串的平均长度。因为需要遍历每个字符串的每个字符。 - 空间复杂度:
O(k)
,其中k
是allowed
字符串的长度,主要用于存储允许的字符集合。
6. 总结
本题展示了处理字符匹配统计问题的两种常见思路:白名单过滤法和逆向排除法。白名单过滤法更直观,而逆向排除法则在某些情况下可能更高效。在实际编程中,我们可以根据具体的输入规模和数据特点选择合适的方法。此外,使用集合(Set)来存储允许的字符可以进一步优化字符查找的效率,将时间复杂度从 O(m)
降低到 O(1)
。
希望这篇解析能帮助你更好地理解如何处理类似的字符匹配统计问题。如果你有任何疑问或其他解法,欢迎在评论区留言讨论!