LeetCode - 771. Jewels and Stones

本文介绍两种方法来计算字符串stones中有多少个字符出现在字符串jewels中。第一种方法通过遍历stones并检查每个字符是否存在于jewels中;第二种方法使用正则表达式移除stones中所有不在jewels中的字符,然后比较移除前后长度的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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中:

  1. 初始化计数器jewelsCount为0
  2. 遍历stones中的每个字符s
  3. s存在于jewels中,计数器加1
  4. 返回计数器值

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 解题思路

另一种巧妙的方法是使用正则表达式一次性匹配所有宝石字符:

  1. 记录stones的原始长度
  2. 构建一个匹配所有jewels中字符的正则表达式
  3. 使用该正则表达式删除stones中所有宝石字符
  4. 计算原始长度与剩余长度的差值,即为宝石数量

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练习的价值所在。希望本文对你理解和解决此类问题有所帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿蒙Armon

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值