Leetcode 1002. 查找共用字符

题目描述

给你一个字符串数组 words ,请你找出所有在 words 的每个字符串中都出现的共用字符( 包括重复字符),并以数组形式返回。你可以按 任意顺序 返回答案。

示例 1:

输入:words = ["bella","label","roller"]
输出:["e","l","l"]

示例 2:

输入:words = ["cool","lock","cook"]
输出:["c","o"]

提示:

  • 1 <= words.length <= 100
  • 1 <= words[i].length <= 100
  • words[i] 由小写英文字母组成

NOTE:由 words[i] 由小写英文字母组成 ,返回的是公共字符,可以想到使用哈希法

卡哥原话:这道题目一眼看上去,就是用哈希法,“小写字符”,“出现频率”, 这些关键字都是为哈希法量身定做的啊

思路:这道题说要返回字符串中的所有公共字符,并且都是由小写英文字母构成,就可以想到使用数组按照26个小写字母相对于‘a’的ascii码的索引数组,数组中存放的是字符的出现次数,整体思路就是统计出搜索字符串里26个字符的出现的频率,然后取每个字符频率最小值,最后转成输出格式就可以了

先统计第一个字符串所有字符出现的次数

 int hash[26] = {0};// 用来统计所有字符串里字符出现的最小频率
        for(int i=0 ;i<words[0].size() ;i++) { // 用第一个字符串给hash初始化
            hash[words[0][i] - 'a']++;
        }

 假设我们有三个字符串作为输入,如下:

["bella", "label", "roller"]

  • 首先,用第一个字符串 "bella" 初始化 hash 数组,记录每个字符的频率。
    • hash['b' - 'a'] = 1
    • hash['e' - 'a'] = 1
    • hash['l' - 'a'] = 2
    • hash['a' - 'a'] = 1

接下来,把其他字符串里字符的出现次数也统计出来一次放在hashOtherStr中。

然后hash 和 hashOtherStr 取最小值,这是本题关键所在,此时取最小值,就是 一个字符在所有字符串里出现的最小次数了。

        for(int i =1; i <words.size() ;i++ ) { // 统计除第一个字符串外字符的出现频率
            memset(hashOtherStr , 0 ,26*sizeof(int));
            for(int j = 0;j<words[i].size() ;j++) {
                hashOtherStr[words[i][j] - 'a']++;
            }
            // 这是关键所在
            for(int k =0; k < 26; k++) {
            // 更新hash,保证hash里统计26个字符在所有字符串里出现的最小次数
               hash[k] = min(hash[k] , hashOtherStr[k]);

            }
        }
  1. 处理第二个字符串:"label"

    • 重置 hashOtherStr 并统计 "label" 中每个字符的频率。
      • hashOtherStr['l' - 'a'] = 2
      • hashOtherStr['a' - 'a'] = 1
      • hashOtherStr['b' - 'a'] = 1
      • hashOtherStr['e' - 'a'] = 1
    • 更新 hash 数组以存储每个字符的最小频率:
      • hash['l' - 'a'] = min(2, 2) = 2
      • hash['a' - 'a'] = min(1, 1) = 1
      • hash['b' - 'a'] = min(1, 1) = 1
      • hash['e' - 'a'] = min(1, 1) = 1
  2. 处理第三个字符串:"roller"

    • 重置 hashOtherStr 并统计 "roller" 中每个字符的频率。
      • hashOtherStr['r' - 'a'] = 2
      • hashOtherStr['o' - 'a'] = 1
      • hashOtherStr['l' - 'a'] = 2
      • hashOtherStr['e' - 'a'] = 1
    • 更新 hash 数组以存储每个字符的最小频率:
      • hash['l' - 'a'] = min(2, 2) = 2 ("l" 在所有字符串中都至少出现2次)
      • hash['e' - 'a'] = min(1, 1) = 1 ("e" 在所有字符串中都至少出现1次)

 此时hash里统计着字符在所有字符串里出现的最小次数,那么把hash转成题目要求的输出格式就可以了。

        // 将hash统计的字符次数,转成输出形式
        for (int i = 0; i < 26; i++) {
            while (hash[i] != 0) { // 注意这里是while,多个重复的字符
                string s(1, i + 'a'); // char -> string
                result.push_back(s);
                hash[i]--;
            }
        }
  • 最终,从 hash 数组中读取每个字符的统计数据,并将其转换为字符串格式输出。
  • 结果:["e", "l", "l"]
  1. 外层循环 (for):遍历从0到25的每个索引 i,这些索引代表了字符从 'a' 到 'z'。

  2. 内层循环 (while):对于每个字符,只要 hash[i] 的值不为0,就进入循环体。

    • string s(1, i + 'a');:这行代码创建一个字符串 s,包含单个字符 i + 'a'。例如,如果 i = 0,那么 i + 'a' 就是 'a',所以 s 就是 "a"
      string 类的构造函数有多种重载形式,其中一种允许创建一个具有特定长度和特定字符的字符串。这行代码 string s(1, i + 'a'); 利用了这种构造函数。

    • result.push_back(s);:将字符串 s 添加到结果向量 result 中。

    • hash[i]--;:将 hash[i] 减1,表示已经将一个实例的字符添加到结果中。

  3. 重复添加:如果 hash[i] 的值是2,while 循环会执行两次,每次都添加相同的字符 i + 'a'result 中,因此,相同的字符会被添加两次。比如,如果 i 对应于字符 'a',且 hash[i] 值为2,则最终 result 中将包含两个 "a"

完整代码 

class Solution {
public:
    vector<string> commonChars(vector<string>& words) {
        vector<string> result;
        if(words.size() == 0) {
            return result;
        }
        int hash[26] = {0};
        for(int i=0 ;i<words[0].size() ;i++) {
            hash[words[0][i] - 'a']++;
        }
        int hashOtherStr[26] = {0};
        for(int i =1; i <words.size() ;i++ ) {
            memset(hashOtherStr , 0 ,26*sizeof(int));
            for(int j = 0;j<words[i].size() ;j++) {
                hashOtherStr[words[i][j] - 'a']++;
            }
            for(int k =0; k < 26; k++) {
               hash[k] = min(hash[k] , hashOtherStr[k]);

            }
        }
         for(int i = 0; i < 26 ;i++) {
                while(hash[i] != 0) {
                    string s(1,i+'a');
                    result.push_back(s);
                    hash[i]--;
                }   
            }
        return result;
    }
};

 参考文章:代码随想录 (programmercarl.com)

  • 9
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值