代码训练(4)LeetCode之字母异位词
Author: Once Day Date: 2024年3月6日
漫漫长路,才刚刚开始…
全系列文章可参考专栏: 十年代码训练_Once-Day的博客-CSDN博客
参考文章:
- 242. 有效的字母异位词 - 力扣(LeetCode)
- 力扣 (LeetCode) 全球极客挚爱的技术成长平台
文章目录
- 代码训练(4)LeetCode之字母异位词
- 1. 原题
- 2. 分析
- 3. 代码实现
- 4. 总结
1. 原题
给定两个字符串
s
和t
,编写一个函数来判断t
是否是s
的字母异位词。**注意:**若
s
和t
中每个字符出现的次数都相同,则称s
和t
互为字母异位词。
例如对于car
和raw
,就不是字母异位词,因为c
和w
没有对上。
2. 分析
该问题是一个简单的编程题目,用C语言来实现,只要要求性能较高(速度90%),一般不浪费内存即可。
题目要求我们编写一个函数,这个函数需要判断两个字符串 s
和 t
是否是字母异位词。如果一个字符串的字母重新排列后能够得到另一个字符串,那么这两个字符串互为字母异位词。换句话说,两个字符串有相同的字母和相同数量的每个字母。
解决这个问题,核心思路是检查两个字符串中每个字母的数量是否完全相同。
- 哈希表法:我们可以使用一个哈希表(或称为字典)来记录字符串
s
中每个字符出现的次数,然后遍历字符串t
,减少哈希表中对应字符的计数。如果最后哈希表中所有字符的计数都是零,则说明t
是s
的字母异位词。 - 数组法:由于题目只提到了字母,我们可以假设输入是 ASCII 字符串,因此可以使用一个大小为 26 的整数数组来代替哈希表。数组的每个位置对应一个字母,值为该字母在字符串
s
中出现的次数。这种方法在空间上更加高效,因为它不需要额外的哈希表结构。 - 排序法:将两个字符串分别排序,如果它们相等,则它们是字母异位词。
如果题目支持大量字符(比如宽字符unicode字符
),那么Hash方法更合适。
这里只考虑26个字母,使用数组法解决效率更高,如下:
- 如果
s
和t
的长度不同,则它们不能是字母异位词,返回false
。 - 创建一个大小为 26 的整数数组来存储每个字母的频率。
- 遍历字符串
s
,对于每个字符c
,在数组中c - 'a'
的位置增加 1。 - 遍历字符串
t
,对于每个字符c
,在数组中c - 'a'
的位置减少 1。 - 遍历整数数组,如果所有位置的值都是 0,则返回
true
;否则,返回false
。
假设我们有两个字符串 s = "anagram"
和 t = "nagaram"
。
- 两个字符串长度相同,继续。
- 创建频率数组
freq[26]
。 - 遍历
s
,更新频率数组:freq['a' - 'a'] = 3, freq['n' - 'a'] = 1
, 等等。 - 遍历
t
,更新频率数组:每个对应字符的频率减 1。 - 最后检查频率数组,所有值都是 0,所以
t
是s
的字母异位词。
性能优化关键点
-
执行速度:直接使用长度为 26 的数组来存储每个字母频率是相当快的操作,因为数组的访问时间是常数时间。
-
内存使用:使用静态大小的数组,而不是动态数据结构如哈希表,可以减少内存开销。
3. 代码实现
bool isAnagram(char* s, char* t) {int16_t s1[26] = {0};while (*s != '\0') {s1[*s - 'a']++;s++;}while (*t != '\0') {if (--s1[*t - 'a'] < 0) {return false;}t++;}for (int i = 0; i < 26; i++) {if (s1[i]) {return false;}}return true;
}
这段代码定义了一个函数 isAnagram
,它用来检测两个输入的字符串 s
和 t
是否为字母异位词。字母异位词是指由相同的字母以不同的顺序组成的单词或短语。
函数的工作原理如下:
- 定义并初始化一个整型数组
s1
用于计数26个英文字母在字符串s
中出现的次数。数组的每个索引对应一个字母(0索引对应 ‘a’,1索引对应 ‘b’,以此类推)。 - 第一个
while
循环遍历字符串s
,通过递增s1
数组相应的计数器来记录每个字母出现的次数。 - 第二个
while
循环遍历字符串t
,同时递减s1
数组中相应字母的计数器。如果某个字母的计数器在递减前已经是0或在递减后变为负数,这意味着字符串t
中这个字母出现的次数多于字符串s
中的次数,或者字符串s
中没有这个字母,因此可以判断两个字符串不是字母异位词,函数返回false
。 - 第三个
for
循环检查s1
数组中的计数器是否都回到了0。如果有任何计数器的值不为0,这意味着字符串s
中有字母没有在字符串t
中出现相同的次数,或字符串t
较短而未能消除s
中的某些字母计数,因此两个字符串也不是字母异位词,函数同样返回false
。 - 如果所有的计数器最终都是0,这意味着两个字符串有相同的字母和相同的字母出现次数,函数返回
true
,表示字符串s
和t
是字母异位词。
运行截图如下所示,可以看到运行效率和内存使用还是非常好的,这里有个注意点,C语言strlen函数开销很大,不能频繁调用,这和Python等动态语言是完全不同的。
4. 总结
这个题目考查了对字符串的基本操作,以及对哈希表和数组数据结构的理解和应用。为了提升解决此类问题的能力,可以加强对数据结构的学习和实践,特别是了解如何根据不同的问题选择合适的数据结构来优化性能。此外,对字符串的常见操作如遍历、比较、哈希编码等的掌握也是非常关键的。
理解和应用。为了提升解决此类问题的能力,可以加强对数据结构的学习和实践,特别是了解如何根据不同的问题选择合适的数据结构来优化性能。此外,对字符串的常见操作如遍历、比较、哈希编码等的掌握也是非常关键的。
Once Day
也信美人终作土,不堪幽梦太匆匆......
如果这篇文章为您带来了帮助或启发,不妨点个赞👍和关注,再加上一个小小的收藏⭐!
(。◕‿◕。)感谢您的阅读与支持~~~