# 1832. 判断句子是否为全字母句 (opens new window)
# 题目描述
全字母句 指包含英语字母表中每个字母至少一次的句子。
给你一个仅由小写英文字母组成的字符串 sentence
,请你判断 sentence
是否为 全字母句 。
如果是,返回 true
;否则,返回 false
。
示例 1:
输入:sentence = "thequickbrownfoxjumpsoverthelazydog"
输出:true
解释:sentence 包含英语字母表中每个字母至少一次。
示例 2:
输入:sentence = "leetcode"
输出:false
提示:
1 <= sentence.length <= 1000
sentence
由小写英语字母组成
相关信息:
- 难度:简单
- 标签:字符串
# 题解
此题是我在准备开始参加周赛之际在上一次周赛的虚拟竞赛中做的。虽然是虚拟竞赛,但是体验了一把,感觉还不错,能做出两道题目,对于我这算法菜鸡来说,真是莫大的鼓励。
这道题目主要的实现思路主要有两种:
- 遍历 26 个字母,判断其全都在 sentence 中。
- 遍历 sentence 所有字符,判断其是否包含全部 26 个字母。
由于 sentence 的长度是不定的,其范围在 1 到 1000 以内,所以我跟倾向于选择第一种思路来实现,这样可以减少遍历消耗。
# 方法一:ASCII 码+简单循环
由于题目中有说明是小写字母,故考虑使用 ASCII 码值来循环。此方法虽看起来简单,但是效率还是不错的,时间空间的消耗都超过了百分之九十。
/**
* @param {string} sentence
* @return {boolean}
*/
var checkIfPangram = function (sentence) {
if (sentence.length < 26) return false;
//长度小于26,必然不是。
let isHave;
for (let i = 97; i < 123; i++) {
isHave = sentence.indexOf(String.fromCharCode(i));
//String.indexOf() 查找是否含有子串,成功返回子串开头的下标,失败返回-1
//String.fromCharCode() 将 ASCII 码值转换为对应的码值。
if (isHave == -1) return false;
}
return true;
};
上边是我想到并实现的方法,很明显,它是前文所言的第一种实现思路。
下面还有许多奇妙的方法,都是从各种大佬的题解中学习到的一些方法,在此做个总结。我会贴出原代码以及写出我觉得可优化的提议并贴出优化后的代码:
# 方法二:转化为数组,并使用 filter()去重
//原代码来自:https://leetcode-cn.com/problems/check-if-the-sentence-is-pangram/solution/js-by-mei-mei-xiang-xue-cyu-yan-a2me/
var checkIfPangram = function (sentence) {
return sentence.split("").filter(function (item, index, arr) {
return arr.indexOf(item) === index;
}).length == 26
? true
: false;
};
这段代码首先使用 split() 方法将 sentence 转化为了字符数组,然后使用了 filter() 来过滤重复字符,实现判断重复的最关键的是使用 indexOf() 方法,因为 indexOf() 始终返回的是从头至尾首次出现的元素的下标或者-1,倘若字符的下标和 indexOf() 不符合,证明其不是首次出现。
这段代码,看代码形式是想写成一行代码解决的样子,但是其中有些写法稍微有点儿繁杂,主要有两点:
- filter 的回调函数可以写成箭头函数形式,更简洁
- 最后的三元表达式没必要写,==返回值与所写的值是一样的。
//优化后的代码
var checkIfPangram = function (sentence) {
return (
sentence.split("").filter((item, index, arr) => arr.indexOf(item) === index)
.length === 26
);
};
//优化后的代码
var checkIfPangram = function (sentence) {
return (
sentence.split("").filter((item, index, arr) => arr.indexOf(item) === index)
.length === 26
);
};
# 方法三:使用 Set 去重
前面方法二最关键的点便是去重,但其使用的是 filter 去重。这里用到了更高级的数据结构——Set,利用 Set 不能存储重复键值对的特性实现去重。
//原代码来自:https://leetcode-cn.com/problems/check-if-the-sentence-is-pangram/solution/js-qu-zhong-pai-xu-by-jingguangyan-yrjm/
var checkIfPangram = function (sentence) {
if (sentence.length < 26) return false;
let arr = Array.from(new Set(sentence));
arr.sort();
return arr.join("") === "abcdefghijklmnopqrstuvwxyz";
};
这段代码是先使用 Set 去重,然后使用 Array.from() 转化为数组,然后使用 Array.form() 排序,排序后再使用 join("") 连接成字符串并与'abcdefghijklmnopqrstuvwxyz'
比较。
这段代码的亮点是直接将 sentence 传入了 Set() 中做去重,但是在后续判断是否包含全部字母时的处理有些复杂,多了转数组,排序,然后转字符串并比较的过程。其实此时想要判断是否包含全部字母,只需要看 Set.size 属性值是否为 26 便好。因为题目的提示中有说 sentence 全部由小写字母构成,不会有其他字符哒。
//原代码来自:https://leetcode-cn.com/problems/check-if-the-sentence-is-pangram/solution/pan-duan-ju-zi-shi-fou-wei-quan-zi-mu-ju-pjrf/
var checkIfPangram = function (sentence) {
var newSet = new Set();
for (var i = 0; i < sentence.length; i++) {
newSet.add(sentence[i]);
}
if (newSet.size == 26) {
return true;
} else {
return false;
}
};
这段代码是先新建了一个 Set 对象 newSet,然后使用了一个 for 循环将每个字符添加到 newSet 中。最后判断长度是否等于 26。
这段代码很简洁,很容易让人理解,不过还有两点可以优化的:
- 不必使用 for 循环,new Set() 可以直接传入一段字符串哒。当传入一段字符串时,它可以自动根据字符去重,且区分大小写,更详细的用法请参考MDN (opens new window)
- 最后这个 if 语句写得有些复杂了,完全可以用一个 return 语句替代
var checkIfPangram = function (sentence) {
var newSet = new Set(sentence);
return newSet.size === 26;
};
var checkIfPangram = function (sentence) {
var newSet = new Set(sentence);
return newSet.size === 26;
};
再简单一步的话,可以直接写成一行代码解决形式:
var checkIfPangram = function (sentence) {
return new Set(sentence).size === 26;
};
# 方法四:利用 Map 去重
前面已经利用 filter 和 set 去重了,但其实 map 也能去重。What?不应该是 Set 吗?
//原代码来自:https://leetcode-cn.com/problems/check-if-the-sentence-is-pangram/solution/li-yong-mapqu-zhong-bing-jian-zhi-by-qyu-3dy1/
var checkIfPangram = function (sentence) {
let map = new Map(),
len = sentence.length;
for (let i = 0; i < len; i++) {
map.set(sentence[i]);
//这里利用了map对象的key值不可重复的特性来达到去重的目的
if (map.size === 26) return true;
}
return false;
};
很惊奇吧?觉得自己学了一个假的 JS?我也是第一次看到这样的用法,日常中去重使用 Set 还是较多的,第一次看见有人使用 map 的 key 值不可重复的特性来达到去重的目的。这很极客~
但是我还是不太推荐这样的用法,毕竟这样的用法可读性较差,如果不是对 Map 所有属性极其了解,很难读懂这段代码,而且它的用法确实也不够规范。
我个人理解的更规范的用法应该如下:
var checkIfPangram = function (sentence) {
let newMap = new Map();
for (let item of sentence) {
if (!newMap.get(item)) {
newMap.set(item, 1);
//这个if的位置是个小细节
if (newMap.size === 26) return true;
}
}
return false;
};
上边代码中返回 true 的 if 判断是一个小细节,其实这个 if 不是一定要放在另一个 if 里面的,只是放在里面可以减少执行它的次数。因为 newMap.size 的值的改变都是在执行的 set 操作之后,这时候判断 size 值是最合适的,如果将其放在另一个 if 外,则每次循环都会进行判断,及时 size 值没有改变也会重复判断,这样就多余了。
以上就是本题的所有题解啦,感谢你能看到这里,如果本文对你有所帮助的话,别忘了给一个 Star 嗷~ 如果你对题解中的代码有不一样的优化意见,也欢迎你在 issue 中指出~ 最重要的是不要忘了点点关注嗷(Github (opens new window)、力扣 (opens new window)),以便获取我最新的题解以及文章通知。
# 参考:
- 判断句子是否为全字母句 (opens new window)
- 利用 Map 去重并剪枝 (opens new window)
- JS (opens new window)
- leet-code 第 237 周-单周赛赛后总结 (opens new window)
- JS 去重排序 (opens new window)
# 全部代码
/*
* @lc app=leetcode.cn id=1832 lang=javascript
*
* [1832] 判断句子是否为全字母句
*
* https://leetcode-cn.com/problems/check-if-the-sentence-is-pangram/description/
*
* algorithms
* Easy (84.47%)
* Likes: 2
* Dislikes: 0
* Total Accepted: 6.8K
* Total Submissions: 8.1K
* Testcase Example: '"thequickbrownfoxjumpsoverthelazydog"'
*
* 全字母句 指包含英语字母表中每个字母至少一次的句子。
*
* 给你一个仅由小写英文字母组成的字符串 sentence ,请你判断 sentence 是否为 全字母句 。
*
* 如果是,返回 true ;否则,返回 false 。
*
*
*
* 示例 1:
*
*
* 输入:sentence = "thequickbrownfoxjumpsoverthelazydog"
* 输出:true
* 解释:sentence 包含英语字母表中每个字母至少一次。
*
*
* 示例 2:
*
*
* 输入:sentence = "leetcode"
* 输出:false
*
*
*
*
* 提示:
*
*
* 1
* sentence 由小写英语字母组成
*
*
*/
// @lc code=start
/**
* @param {string} sentence
* @return {boolean}
*/
var checkIfPangram = function (sentence) {
let newMap = new Map();
for (let item of sentence) {
if (!newMap.get(item)) {
newMap.set(item, 1)
if (newMap.size === 26) return true;
}
}
return false;
};
// @lc code=end
var checkIfPangram = function (sentence) {
if (sentence.length < 26) return false;
let isHave;
for (let i = 97; i < 123; i++) {
isHave = sentence.indexOf(String.fromCharCode(i));
if (isHave == -1) return false;
}
return true;
};
var checkIfPangram = function (sentence) {
//filter去重
return sentence.split('').filter((item, index, arr) => arr.indexOf(item) === index).length === 26
};
var checkIfPangram = function (sentence) {
var newSet = new Set(sentence);
return newSet.size == 26;
};
var checkIfPangram = function (sentence) {
//直接 set 去重
return new Set(sentence).size === 26;
};