题目要求:给你两个字符串:ransomNote
和 magazine
,判断 ransomNote
能不能由 magazine
里面的字符构成。
如果可以,返回 true
;否则返回 false
。
magazine
中的每个字符只能在 ransomNote
中使用一次。
这道题是对两个字符数组进行处理。首先考虑所有情况。
由于所有字符都只能使用一次,所以当magazine中的字符数少于ransomNote时,恒为false。
当满足数量要求后,可以比较两字符串中的字母数量。利用嵌套for循环可以实现字母的匹配。将找到的两字母置为其对应的大写。目的是不影响后续的循环检查。
#include<string.h>
bool canConstruct(char* ransomNote, char* magazine) {
if (strlen(ransomNote) > strlen(magazine))
return 0;
int make = 0;
for (int i = 0; i < strlen(ransomNote); i++)
{
for (int j = 0; j < strlen(magazine); j++)
{
if (ransomNote[i] == magazine[j])
{
ransomNote[i]-=32;
magazine[j] -=32;
make++;
}
}
}
if (make == strlen(ransomNote))
return 1;
else
return 0;
}
显然,这么多字符对比肯定超出时间限制
嵌套的for循环让时间复杂度上了一个量级,如何减少时间复杂度呢?
减少for循环的嵌套层数。
这道题要求统计的是26个字母的种类和个数。字母范围已知。所以我们可以定义一个整型数组,利用一层for循环统计 magazine
中每个字母出现的次数。之后再利用一层for循环统计ransomNote中各字母出现的次数。当ransomNote中出现某一个字母时便减去整型数组中对应角标中的数字。当数字小于0时则证明magazine
不存在对应数量的字符。一层for循环即解决了问题。
#include<string.h>
bool canConstruct(char* ransomNote, char* magazine)
{
int c[26] = { 0 };
if (strlen(ransomNote) > strlen(magazine))
return false;
for (int i = 0; i < strlen(magazine); i++)
{
c[magazine[i] - 'a']++;
}
for (int i = 0; i < strlen(ransomNote); i++)
{
c[ransomNote[i] - 'a']--;
if (c[ransomNote[i] - 'a'] < 0)
return false;
}
return true;
}
通过了!