LeetCode - 771. Jewels and Stones
在LeetCode的算法世界里,771题"Jewels and Stones"以其简洁的题目描述和多样的解法吸引着众多学习者。本题要求我们统计字符串stones
中有多少字符同时出现在字符串jewels
中,看似简单的问题背后却蕴含着不同的解题思路和性能优化技巧。
1. 问题本质分析
题目给出两个字符串:
jewels
:由代表宝石的字符组成,且每个字符唯一stones
:由代表石头的字符组成
我们需要统计stones
中有多少字符属于jewels
中的宝石类型。例如,若jewels = "aA"
且stones = "aAAbbbb"
,则返回结果应为3
(1个’a’和2个’A’)。
2. 基础解法:字符遍历匹配
2.1 解题思路
最直观的方法是遍历stones
中的每个字符,检查它是否存在于jewels
中:
- 初始化计数器
jewelsCount
为0 - 遍历
stones
中的每个字符s
- 若
s
存在于jewels
中,计数器加1 - 返回计数器值
2.2 代码实现
- JavaScript版本:
/**
* @param {string} jewels
* @param {string} stones
* @return {number}
*/
var numJewelsInStones = function(jewels, stones) {
let jewelsCount = 0;
for (let s of stones) {
if (jewels.includes(s)) {
jewelsCount++;
}
}
return jewelsCount;
};
- Python版本:
class Solution:
def numJewelsInStones(self, jewels: str, stones: str) -> int:
jewels_count = 0
for s in stones:
if s in jewels:
jewels_count += 1
return jewels_count
2.3 复杂度分析
- 时间复杂度:O(n*m),其中n是
stones
的长度,m是jewels
的长度 - 空间复杂度:O(1),只使用了固定的额外空间
这种方法简单易懂,但在处理长字符串时效率较低,因为每次检查字符是否存在都需要遍历jewels
字符串。
3. 进阶解法:正则表达式匹配
3.1 解题思路
另一种巧妙的方法是使用正则表达式一次性匹配所有宝石字符:
- 记录
stones
的原始长度 - 构建一个匹配所有
jewels
中字符的正则表达式 - 使用该正则表达式删除
stones
中所有宝石字符 - 计算原始长度与剩余长度的差值,即为宝石数量
3.2 代码实现
JavaScript版本:
/**
* @param {string} jewels
* @param {string} stones
* @return {number}
*/
var numJewelsInStonesReg = function(jewels, stones) {
let stonesLength = stones.length;
let jewelsReg = eval(`/${jewels.split('').join('|')}/g`);
stones = stones.replace(jewelsReg, '');
return stonesLength - stones.length;
};
3.3 复杂度分析
- 时间复杂度:O(n),主要由字符串替换操作决定
- 空间复杂度:O(m),正则表达式的构建需要额外空间
这种方法通过正则表达式实现了一次性匹配多个字符,理论上效率更高,但在实际应用中可能受到正则表达式引擎性能的影响。
4. 性能优化思考
尽管上述两种方法都能解决问题,但它们并非最优。例如,使用哈希集合可以进一步优化字符查找的效率:
var numJewelsInStones = function(jewels, stones) {
const jewelsSet = new Set(jewels);
let count = 0;
for (let s of stones) {
if (jewelsSet.has(s)) {
count++;
}
}
return count;
};
这种方法将字符查找的时间复杂度从O(m)降低到O(1),整体时间复杂度优化为O(n+m),空间复杂度为O(m)。
5. 总结与启示
本题通过简单的字符串匹配问题,引导我们思考不同算法的性能差异。在实际开发中,我们应该根据数据规模和特性选择合适的解决方案:
- 对于小规模数据,基础的遍历方法足够简洁明了
- 对于大规模数据,使用哈希集合等高效数据结构能显著提升性能
- 正则表达式虽然强大,但在性能敏感场景中需谨慎使用
通过不断探索一题多解,我们不仅能加深对算法的理解,还能培养优化思维,这正是LeetCode练习的价值所在。希望本文对你理解和解决此类问题有所帮助!