题目简介:
有两个字符串,一个常字符串,一个短字符串,以最快的时间判断短字符串中所有的字符是不是在长字符串中出现过。
如:
string strShort = "AbBBcC"; //短字符串
string strLong = "aAbBBcCdd"; //长字符串
段字符串中所有的字符都在长字符串中出现过,所以答案返回TRUE。
再如:
string strShort = "AbBBcCx"; //短字符串
string strLong = "aAbBBcCdd"; //长字符串
段字符串中的x在长字符串中没有出现过,答案返回FALSE
解决方案:
设短字符串长度为n,长字符串长度为m。
1、简单暴力搜索,两层循环,时间复杂度为O(n * m)
方法简单暴力,不再赘述;
2、空间换时间
其实很多优化时间复杂度的问题,都可以从以空间换时间的角度去考虑,这是一个可以通用的原则。
本题中我采用一个数组来统计长字符串中每个字符出现的次数,然后再轮询短字符串。如果该字符串对应到次数数组为0,那么证明该字符没有在长字符串中出现过,则返回FALSE。
【时间复杂度分析】:
轮询长字符串,统计每一个字符出现的次数,时间复杂度为O(n);
轮询短字符串,查寻该位置处的次数数组是否为0,时间复杂度为O(m);
总的时间复杂度为:O(n + m)。
【空间复杂度分析】
本代码中安排了一个52大小数组来记录每个数组出现的次数,之所以是52,我主要是考虑到有大小写的问题。
源代码:
#include <iostream>
#include <string>
using namespace std;
bool CheckStr(string strShort, string strLong);
void main()
{
string strShort = "AbBBcC"; //短字符串
string strLong = "aAbBBcCdd"; //长字符串
if(CheckStr(strShort, strLong))
{
cout << "TRUE";
}
else
{
cout << "FALSE";
}
system("pause");
}
bool CheckStr(string strShort, string strLong)
{
/* 申请一个52大小的数组用于存储每个字符出现的次数,主要考虑到同时存在大小写 */
int hash[52] = {0};
int index = 0;
/* 将长字符串出现的次数统计到数组中 */
for (int i = 0; i < strLong.length(); i++)
{
/* 如果是大写字母 */
if ((strLong[i] >= 'A') && (strLong[i] <= 'Z'))
{
hash[strLong[i] - 'A']++;
}
else if ((strLong[i] >= 'a') && (strLong[i] <= 'z'))
{
/* 小写字母从下标26开始存储 */
hash[strLong[i] - 'a' + 26]++;
}
else
{
cout << "string error";
return false;
}
}
/* 通过上面的步骤已经将长字符串排序完,下面将轮训短字符串 */
for (int i = 0; i < strShort.length(); i++)
{
/* 如果是大写字母 */
if ((strShort[i] >= 'A') && (strShort[i] <= 'Z'))
{
index = strShort[i] - 'A';
}
else if ((strShort[i] >= 'a') && (strShort[i] <= 'z'))
{
/* 小写字母从下标26开始存储 */
index = strShort[i] - 'a' + 26;
}
/* 如果hash中对应下标的内容为零,则证明长字符串中没有出现过该字符,直接return false */
if (0 == hash[index])
{
return false;
}
}
/* 走到这一步都还没有return false,说明所有的字符都出现过,直接return true */
return true;
}