题目描述
全字母句 指包含英语字母表中每个字母至少一次的句子。
给你一个仅由小写英文字母组成的字符串 sentence ,请你判断 sentence 是否为 全字母句 。
如果是,返回 true ;否则,返回 false 。示例 1:
输入:sentence = “thequickbrownfoxjumpsoverthelazydog”
输出:true
解释:sentence 包含英语字母表中每个字母至少一次。示例 2:
输入:sentence = “leetcode”
输出:false提示:
1 <= sentence.length <= 1000
sentence 由小写英语字母组成
方法一:哈希表
思路:
- 设置了计数器 cnt,初值为 26, 每遇到一个第一次出现在句子中的字母,计数器的值就减一,当计数器值为 0 的时候,说明这个句子是 全字母句。
- 设置了 哈希表 s ,用于记录句子中字母的出现次数,作为 判定「字母是否是第一次出现在句子中」的依据。
- 依次遍历字符串,如果该字符串第一次出现,那么 s[sentence[i] - ‘a’] == 0,此时 cnt – ,如果 cnt 为 0 的时候,返回 true (在这一步很可能会提前结束循环,不用把整个字符串都遍历一遍);否则,如果整个字符串遍历结束,则说明没有提前结束循环,表示 cnt 不为 0,也就是说, 这不是一个 全字母句,返回 false。
情况
- 通过;
收获
- 这一道题是在回家的动车上完成的,幸好比较简单,可以用 ipad 作答。
- 我认为我的解法会比官方题解稍微好一点,因为我的方法除非在最坏的情况下(遍历到最后一个字母),否则对于全字母句,很大可能都能够提前结束循环,时间大大缩短了。
而官方题解的方法:进行了两次循环,第一次是遍历整个字符串,每出现一个新字母,在哈希表上标记为 1 ,第二次是遍历这个哈希表,如果哈希表中的值全为 1 ,则返回 true , 否则返回false。它的时间复杂度为: O(n + c);时间复杂度:O(n),n 为 字符串长度;
空间复杂度:O(C),这里 C 为 26,即哈希表的长度;
class Solution {
public:
bool checkIfPangram(string sentence) {
int cnt = 26;
vector<int> s(26);
for(int i=0; i< sentence.size(); ++i){
if(!s[sentence[i] - 'a']){
s[sentence[i] - 'a'] ++;
cnt --;
if(!cnt) return true;
}
}
return false;
}
};
方法二:二进制表示集合
思路:
- 第一种方法使用了一个长度为 26 的数组来记录 26 个字母,那么可以用一个长度为 26 的二进制数字串来表示 26 个字母,这个二进制数字使用 32 位带符号的整形变量。
- 二进制数字中第 i 位表示该字母的出现情况,如果该位置上的字母出现过了,那么第 i 位为 1 。第 0 位 表示 字母 ‘a’ 的出现情况(‘a’ - ‘a’) ,依次类推其他位置表示的字母;
- 初始化整形变量 exist 为 0, 遍历 sentence 中的每个字符 c , 如果 c 是字母表中第 i (0 <= i <= 25) 位字母,就将 exist 的二进制表示中第 i 位赋值为 1。在实现过程中,将 exist 与 2i 做异或运算, 2i 通过左移实现。
- 最后,判断这个二进制数字是否全为 1 ,即为 226 - 1 ,这样说明它是全字母串,返回 true ,否则返回 false。
情况
- 通过;
收获
- 这个方法只使用了一个整型变量,空间复杂度只为 O(1)。
时间复杂度:O(n)
空间复杂度:O(1)
class Solution {
public:
bool checkIfPangram(string sentence) {
int exist = 0;
for(auto c : sentence){
exist |= (1 << (c - 'a'));
}
// 1<<26 即 2^26^
return exist == (1 << 26) - 1;
}
};