【力扣】771. 宝石与石头

268 阅读2分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

原题链接

771. 宝石与石头 - 力扣(LeetCode) (leetcode-cn.com)

题目描述

 给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头。 S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。

J 中的字母不重复,J 和 S中的所有字符都是字母。字母区分大小写,因此"a"和"A"是不同类型的石头。

测试用例

示例 1:

输入: J = "aA", S = "aAAbbbb"
输出: 3

示例 2:

输入: J = "z", S = "ZZ"
输出: 0

参数限制

  • S 和 J 最多含有50个字母。
  • J 中的字符不重复。

分析

用通俗的话来说,有两个字符串 a, b,其中,a 中的单个字符都不会重复,需要判断出来,b 中的单个字符如果出现在 a 中,则需要计数 +1,最后返回这个值

代码

一个简单的解法,将 a 中的数据转化为 Set,然后遍历 b 的字符,判断并计数

var numJewelsInStones = function(jewels, stones) {
    let set = new Set(jewels.split(''));
    let count = 0;
    stones.split('').forEach(n=>{
        if(set.has(n)) count++;
    })
    return count;
};

image.png

从答案来,耗时米勉强,但内存占用不尽人意

解法 2

上面的方法是使用 Set 来优化检索效率,总的执行时间需要分别遍历 2 个字符串,再加上 hashset 的检索耗时

这次,我们优化掉 hashset 的检索,直接使用一个 object 来存储字符串 b 中各个字符出现的次数

然后再遍历一次 a,遍历的时候,对每个字符 n 做 sum += obj[n] || 0,简单粗暴

var numJewelsInStones = function(jewels, stones) {
    let obj = {};
    stones.split('').forEach(n=>{
        obj[n]=(obj[n]||0)+1;
    })
    let count = 0;
    jewels.split('').forEach(n=>count += (obj[n]||0));
    return count;
};

image.png

但这效果就有点不太满意了,讲道理,hash 的检索耗时去掉了,使用 obj 来替代 set,内存也没降到多少

官方题解

使用的 Set,但写起来让人更加惊艳

var numJewelsInStones = function(jewels, stones) {
    const jewelsSet = new Set(jewels.split(''));
    return stones.split('').reduce((prev, val) => {
        return prev + jewelsSet.has(val);
    }, 0);
};

多次测试后,发现确实提升了一点点


今天的力扣刷题就分享到这里,感谢大家的阅读~