LeetCode771 宝石与石头

题目描述

给定一个字符串 jewels,它代表石头中宝石的类型;另有一个字符串 stones,代表我们拥有的石头。其中,stones 里的每个字符对应一种石头类型,任务是要精准地统计出在 stones 当中,属于 jewels 所定义的宝石类型的石头究竟有多少。这里需特别注意,字母区分大小写,像 "a""A" 会被视作不同类型的石头。

解题思路

暴力解法:双层循环遍

最初想到的最直白的方法,就是利用双层 for 循环嵌套。外层循环负责逐个遍历 stones 中的字符,对于每一个 stones 里的字符,内层循环则遍历 jewels 字符串,去逐一比对是否有匹配的宝石类型。一旦找到匹配项,立马给计数器 count 加 1,随后中断内层循环,继续检查 stones 的下一个字符。

cs 复制代码
#include <stdio.h>
#include <string.h>

// 函数用于统计在stones中属于jewels定义的宝石类型的字符个数
int numJewelsInStones(char* jewels, char* stones) {
    int count = 0;
    // 遍历stones字符串中的每个字符
    for (int i = 0; stones[i]!= '\0'; i++) {
        // 对于stones中的每个字符,遍历jewels字符串进行匹配
        for (int j = 0; jewels[j]!= '\0'; j++) {
            if (stones[i] == jewels[j]) {
                count++;
                break;  // 一旦匹配成功,就不用继续在jewels中找了,直接去看下一个stones中的字符
            }
        }
    }
    return count;
}

int main() {
    char jewels[] = "aA";  // 可以自行修改这里的宝石类型字符串内容
    char stones[] = "aAAbbbb";  // 可以自行修改这里的拥有石头类型字符串内容
    int result = numJewelsInStones(jewels, stones);
    printf("在拥有的石头中宝石的数量是: %d\n", result);
    return 0;
}

这种方法虽然易于理解,代码逻辑清晰,但时间复杂度不容小觑,达到了 O(m * n),其中 mstones 字符串长度,njewels 字符串长度。想象一下,当 stonesjewels 都很长时,计算量会呈指数级增长,效率明显受限。

方法二:

哈希表优化解法:空间换时间

为了突破暴力解法的效率瓶颈,哈希表闪亮登场。其核心思路是预先利用一个数组(这里模拟哈希表,假设 ASCII 码值范围能涵盖处理字符)来存储宝石类型信息。

首先,遍历 jewels 字符串,将其中出现的字符对应的数组位置标记为 1,这就像是给宝石类型做了个快速索引目录。接着,遍历 stones 字符串时,只需凭借字符的 ASCII 码值瞬间定位到数组对应位置,若值为 1,那该字符就是宝石类型,计数器 count 顺势加 1。

cs 复制代码
#include <stdio.h>
#include <string.h>

// 函数用于统计在stones中属于jewels定义的宝石类型的字符个数
int numJewelsInStones(char* jewels, char* stones) {
    int hashTable[128] = {0};  // 假设ASCII码值范围足够涵盖我们要处理的字符,初始化哈希表数组元素都为0
    int count = 0;
    // 先将jewels中的字符对应的哈希表位置标记为1,表示存在这样的宝石类型
    for (int i = 0; jewels[i]!= '\0'; i++) {
        hashTable[(int)jewels[i]] = 1;
    }
    // 遍历stones,通过哈希表快速判断是否是宝石类型
    for (int j = 0; stones[j]!= '\0'; j++) {
        if (hashTable[(int)stones[j]] == 1) {
            count++;
        }
    }
    return count;
}

int main() {
    char jewels[] = "aA";  // 可根据需求修改宝石类型字符串内容
    char stones[] = "aAAbbbb";  // 可根据需求修改拥有石头类型字符串内容
    int result = numJewelsInStones(jewels, stones);
    printf("在拥有的石头中宝石的数量是: %d\n", result);
    return 0;
}

经此优化,时间复杂度大幅降至 O(m + n),尽管额外开辟了数组空间用于存储哈希表信息,但在数据量庞大时,计算效率的提升立竿见影,完美诠释了 "空间换时间" 的编程技巧精髓。

总结与启示

这道题犹如一面镜子,清晰映照出编程中效率权衡的艺术。从简单直接的暴力解法,到巧用数据结构优化的进阶之路,我们领悟到面对问题,思维不能局限于最初的直观想法。当性能瓶颈显现,积极探寻更优算法结构、大胆借助数据结构独特优势,才能在程序执行效率的赛道上弯道超车。

无论是日常刷题备战面试,还是实际项目开发优化性能,这种不断打磨解法、追求极致的精神,都将成为我们手中披荆斩棘的利刃,助力我们在代码世界里畅行无阻,攻克一个又一个难题。希望这次分享能给大家带来新的启发,一起在编程之旅中不断进阶!

相关推荐
逆向菜鸟6 分钟前
【摧毁比特币】椭圆曲线象限细分求k-陈墨仙
python·算法
DolphinDB14 分钟前
DolphinDB 回测插件快速上手
算法
利刃大大32 分钟前
【动态规划:路径问题】最小路径和 && 地下城游戏
算法·动态规划·cpp·路径问题
武大打工仔1 小时前
用 Java 复现哲学家就餐问题
算法
要做朋鱼燕1 小时前
【数据结构】用堆解决TOPK问题
数据结构·算法
秋难降2 小时前
LRU缓存算法(最近最少使用算法)——工业界缓存淘汰策略的 “默认选择”
数据结构·python·算法
CoovallyAIHub3 小时前
线性复杂度破局!Swin Transformer 移位窗口颠覆高分辨率视觉建模
深度学习·算法·计算机视觉
点云SLAM4 小时前
Eigen中Dense 模块简要介绍和实战应用示例(最小二乘拟合直线、协方差矩阵计算和稀疏求解等)
线性代数·算法·机器学习·矩阵·机器人/slam·密集矩阵与向量·eigen库
renhongxia14 小时前
大模型微调RAG、LORA、强化学习
人工智能·深度学习·算法·语言模型