>[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
})
})
}
~~~
- 刷题准备
- 统计数组中元素出现次数
- Leetcode -- 442数组中重复的数据
- leetcode -- 448 找到所有数组中消失的数字
- 字符类似题
- Leetcode -- 1002 查找共用字符
- Leetcode -- 1370上升下降字符串
- 指针类题解
- Leetcode -- 283 移动零
- Leetcode -- 26. 删除有序数组中的重复项
- Leetcode -- 80. 删除有序数组中的重复项 II
- Leetcode -- 27. 移除元素
- Leetcode -- 344. 反转字符串
- Leetcode -- 125 验证回文串
- Leetcode -- 11 盛最多水的容器
- Leetcode -- 1480. 一维数组的动态和