字符串的包含
题目描述
给定字符串str1与字符串str2,求解str1是否包含str2中所有元素。注意,这不是求子串。如:”ABCD”与”BCA”,返回结果true;”ABCD”与”AA”返回结果true;”ABCD”与”BCE”返回结果false。
解法一:蛮力轮询
对于str2中每个元素,到str1中去遍历一遍,若无,则在str1中使用的索引应该会超过str1的边界。具体代码如下:
int string_contain(const char *str1, const char *str2)
{
int len1 = (int) strlen(str1);
int len2 = (int) strlen(str2);
int i, j;
for (i = 0; i < len2; ++i) {
for (j = 0; j < len1 && str1[j] != str2[i]; ++j) {
;
}
if (j >= len1) {
return false;
}
}
return true;
}
假设str1长度为m,str2长度为n,时间复杂度O(m * n)。
解法二:排序后轮询
对于str1与str2,先进行排序处理,假设str1长度为m,str2长度为n,两者使用快速排序后,时间复杂度为O(m * logm) + O(n * logn),之后便是轮询,时间复杂度为O(m + n)。具体代码如下:
int string_contain(string &str1, string &str2)
{
sort(str1.begin(), str1.end());
sort(str2.begin(), str2.end());
int i, j;
for (i = 0; i < str2.length(); ++i) {
for (j = 0; j < str1.length() && str1[j] < str2[i]; ++j) {
;
}
if (j >= str1.length() || str1[j] > str2[i]) {
return false;
}
}
return true;
}
对于长度较长的字符串,解法二优于解法一,但如果数据大多都是长度较短的字符串,那解法一反而可能会比解法二好一些。
解法三:素数相乘
str1与str2中每个元素对应一个素数,如:’A’对应2,’B’对应3,’C’对应5,依次对应。str1中所有元素对应的素数相乘,str2中所有元素对应的素数相乘,两个结果求模,如果结果为0,则可判断str1中包含str2中的所有元素,反之不包含。具体代码如下:
int string_contain(const char *str1, const char *str2)
{
int prime[] = {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
101
};
int i;
long long f = prime[(int) (str1[0] - 'A')];
for (i = 1; i < strlen(str1); ++i) {
int x = prime[(int) (str1[i] - 'A')];
if (f % x) {
f *= x;
}
}
for (i = 0; i < strlen(str2); ++i) {
int x = prime[(int) (str2[i] - 'A')];
if (f % x) {
return false;
}
}
return true;
}
这个解法对于字符串很短的情况可以解决,对于字符串长一点的情况就存在整数溢出的问题,严格来说,这不算一种正确的解法,前16个素数相乘就会产生溢出,所以仅能适用于一些情况。假设str1长度为m,str2长度为n,时间复杂度为O(m + n)。
解法四:位运算
英文字符大小写都算有52个,仅算大写的话,只有26个,这样就可以使用一个32位大小的int,采用对1进行”<<”运算,再与该int做”&”运算的方式作为记录,根据该记录去判断是否包含相应的串了。具体代码如下:
int string_contain(const char *str1, const char *str2)
{
int hash = 0;
int i;
for (i = 0; i < strlen(str1); ++i) {
hash |= (1 << ((int) (str1[i] - 'A')));
}
for (i = 0; i < strlen(str2); ++i) {
if ((hash & (1 << ((int) (str2[i] - 'A')))) == 0) {
return false;
}
}
return true;
}
从代码上能够清晰看到思路,这里需要保证int至少有32位。空间复杂度为O(1),时间复杂度为O(m + n)。效率上是比较高的。