[路飞]_leetcode 884. 两句话中的不常见单词

172 阅读2分钟

「这是我参与2022首次更文挑战的第13,活动详情查看:2022首次更文挑战

884. 两句话中的不常见单词

句子 是一串由空格分隔的单词。每个 单词 仅由小写字母组成。

如果某个单词在其中一个句子中恰好出现一次,在另一个句子中却 没有出现 ,那么这个单词就是 不常见的 。

给你两个 句子 s1 和 s2 ,返回所有 不常用单词 的列表。返回列表中单词可以按 任意顺序 组织。

示例 1:

输入:s1 = "this apple is sweet", s2 = "this apple is sour"
输出:["sweet","sour"]

示例 2:

输入:s1 = "apple apple", s2 = "banana"

输出:["banana"]  

提示:

1 <= s1.length, s2.length <= 200
s1 和 s2 由小写英文字母和空格组成
s1 和 s2 都不含前导或尾随空格
s1 和 s2 中的所有单词间均由单个空格分隔

分析

首先根据题意中对不常见单词是这样定义的其中一个句子中恰好出现一次,在另一个句子中却没有出现,那么这个单词就是不常见的。

那么通过题意中对不常见单词,可以看出如果一个单词在s1中出现一次并且在s2中没有出现;或者是一个单词在s2中出现一次并且在s1中没有出现。结合这俩点我们不难发现其实也就是一个单词只出现一次,那么我们可以利用这个当作我们的破局点。

同时在提示中提到s1s2 都不含前导或尾随空格所以说我们不需要通过trim方法来去掉首尾的空格。在提示中还提到过1 <= s1.length, s2.length <= 200也就是对空间的要求也是不大的。当然由于对空间要求不大是这道题被定义为简单题的必要条件了。

逐步实现

  • 首先我们可以把s1与s2合二为一变成一句话,并通过split方法以' '作为条件转换成为数组wordsArr

let wordsArr = (s1 + ' ' + s2).split(' ')

  • 定义一个map对象来统计每个单词出现的次数,这里我们可以通过reduce方法来实现
let wordsMap = wordsArr.reduce((wordsMap, word) => {
        return wordsMap.set(word, (wordsMap.get(word) || 0) + 1)
    }, new Map())

这边我们简单来说说reduce方法,通过查阅MDN我可以看出reduce方法是有一个回调函数与一个可选参数初始化(initialValue)。在回调函数中我们可以获取当前迭代器(accumulator)与当前元素(currentValue)。

  • 最后我们只需要通过filter方法筛选出在wordsMap中出现一此的单词即可。

``js wordsArr.filter(word => { return wordsMap.get(word) === 1 })


## 完整代码实现

```js

/**
 * @param {string} s1
 * @param {string} s2
 * @return {string[]}
 */
var uncommonFromSentences = function(s1, s2) {
    let wordsArr = (s1 + ' ' + s2).split(' ') // 将s1与s2合并起来并转换为数组
    let wordsMap = wordsArr.reduce((wordsMap, word) => {
        return wordsMap.set(word, (wordsMap.get(word) || 0) + 1)
    }, new Map()) // 通过map对象统计每个单词出现的数量
    return wordsArr.filter(word => {
       return wordsMap.get(word) === 1
    }) // 最后返回只出现一次的单词集合
};