ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
>[success] # 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] 由小写英文字母组成 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/find-common-characters 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 >[danger] ##### 第一次解题思路 用**Map** 作为记录字符串出现次数,对比出现次数最小值即为出现的**共用字符** 举个例子 ["bella","zabel","roller"] ![](https://img.kancloud.cn/ee/44/ee44af5b518fccc393b60c57966e4fd8_813x776.png) ![](https://img.kancloud.cn/35/a2/35a26734c884d84ad67a82838ae6bfd4_492x242.png) ~~~ var commonChars = function (words) { // 用map 计算出第一组每个字母个数 const minMap = {} const [firstGroup, ...otherGroup] = words for (let w of firstGroup) { if (!minMap[w]) { minMap[w] = 0 } minMap[w]++ } // 计算其他组单词出现频率 otherGroup.forEach((word) => { const currentMap = {} for (let w of word) { if (minMap[w] && !currentMap[w]) { currentMap[w] = 0 } currentMap[w]++ } // 比较最少次数 for (let k in minMap) { // 跟新最少出现次数频率 minMap[k] = Math.min(minMap[k], currentMap[k] || 0) } }) const res = [] for (let k in minMap) { let count = minMap[k] while (count) { res.push(k) count-- } } return res } ~~~ >[info] ## 题解 题中说`由小写英文字母组成` 因此只能有**26**个单词,利用固定26这个条件可以用**数组形式**,创建一个长度为26的数组,将字母找到对应数组位置可利用**ASCII**码,当想获取对应单词时候可以用**ASCII**反解析映射对应的字母 ![](https://img.kancloud.cn/37/35/37355e02008c516e3d912a6e97a1a504_966x754.png) 将每组收集,对比每项最小值,即可得到**共用字符** ![](https://img.kancloud.cn/c7/2c/c72ccb09f7de4ae71220ab531271bc65_902x748.png) >[danger] ##### js 题解 ~~~ var commonChars = function (words) { // 将第一组值映射记录到对应数组上 const [firstGroup, ...otherGroup] = words // 创建长度26的数组保存对应 字母 const minWordCountsLs = new Array(26).fill(0) for (let w of firstGroup) { // 都是小写字母 为了找到属于数组对应映射位置使用,a的ASCII 码为97 // 因此 减掉97 例如 a 原本应该保存数组0的位置 97-97 =0 const idx = w.charCodeAt(0) - 97 ++minWordCountsLs[idx] } // 依次比较找到 相互直接最小的出现次数替换 for (let other of otherGroup) { // 计算出当前组字符出现次数 const currentCountsLs = new Array(26).fill(0) for (let w of other) { const idx = w.charCodeAt(0) - 97 ++currentCountsLs[idx] } // 循环比较更新最小出现值数组 minWordCountsLs.forEach((item, index) => { minWordCountsLs[index] = Math.min(item, currentCountsLs[index]) }) } // 将出现此次字母记录 return minWordCountsLs.reduce((acc, count, index) => { while (count) { acc.push(String.fromCharCode(index + 97)) count-- } return acc }, []) } ~~~ >[danger] ##### java ~~~ import java.util.List; import java.util.ArrayList; public class Solution { public List<String> commonChars(String[] words) { // 创建一个26长度数组 int[] minLs = new int[26]; // 循环第一组数组记录到数组中 for(char c:words[0].toCharArray()){ // 减掉a从0开始可以映射对应数组 int idx = c -'a'; minLs[idx]++; } // 依次寻其他项找到最小数组 for(int i=1;i< words.length;i++){ // 记录数组长度 int[] currentLs = new int[26]; // 循环字符串 for(char c:words[i].toCharArray()){ int idx = c -'a'; currentLs[idx]++; } // 循环找到相交出现最小次数 for(int j=0;j<26;j++){ minLs[j] = Math.min(minLs[j],currentLs[j]); } } // 求出对应字母 List<String> wLs = new ArrayList<>(); for(int i=0;i<26;i++){ int counts = minLs[i]; while (counts>0){ wLs.add(String.valueOf((char)(i+'a'))); counts--; } } return wLs; } } ~~~ >[info] ## 其他解题思路 两个字符进行比较,如果有相同的则记录下来,但要注意需要将已经比较后的值去处,否则会出现重复比较 ![](https://img.kancloud.cn/88/fd/88fdc91667340f345b8dbbfbda92d77c_684x359.png) ~~~ var commonChars = function (words) { return words.reduce((acc, cur) => { return [...acc].filter((item) => { const flag = cur.includes(item) cur = cur.replace(item, '') return flag }) }) } ~~~