(0001)刪除字符串中的公共字符
題目: 輸入兩個字符串, 從第一字符串(下文稱爲x)中刪除第二個字符串(下文簡稱爲y)中所有的字符. 例如, 輸入
They are students.
和aeiou
, 則刪除之後的第一個字符串變成Thy r stdnts.
解題思路
最簡單的思路
兩層循環遍歷, 每遍歷到字符串 y 中的一個字符, 就在字符串 x 中找到相同的字符, 找到之後刪除它,並將字符串 x 後面的字符整體向前移動1位。所以這個過程的時間複雜度是O(n³).
優化 - 解決順序存儲結構中刪除後整體移動的問題
刪除一個字符的另一個思路是: 不是某個指定的字符就保留
, 按照這種思維方式, 可以將需要保留的字符覆蓋在原來的字符串上, 此時需要兩個標記變量(或者說指針), 一個用於控制字符串 x 的整體遍歷過程,一個記錄要覆蓋的位置, 這樣的話,我們就能避免每一次刪除後的整體平移,時間複雜度優化爲O(n²)
, 如下圖所示.
優化 - 引入hash表, 避免雙層遍歷
O(n²)
的時間複雜度是由遍歷兩個字符串產生的,引入hash表能夠避免循環嵌套的問題,我採用的方式是對字符串 y, 建立一個hash表, 在字符串 y 中出現的字符, 在hash表中的值爲1, 反之爲0.- 參考標點符號和字母的ASCII碼值, hash範圍選成256就足夠了.
關於選用hash表的方式: 用一個O(256)的空間複雜度,將時間複雜度從O(n^2)將爲O(n),如果n很大的話,這個替換是值得的。
show the code
#include "iostream"
using namespace std;
void DeleteChar(char arr1[], char arr2[]);
int main()
{
char str1[] = "They are students.";
char str2[] = "aeiou";
cout<<str1<<endl;
DeleteChar(str1, str2);
cout<<str1<<endl;
getchar();
return 0;
}
void DeleteChar(char *arr1, char *arr2)
{
if (arr1 == NULL && arr2 == NULL) return;
// 創建hash表
int hash_table[256] = { 0 };
char *p1 = arr1;
char *p2 = arr2;
int index =0;
// 遍歷字符串y
while(*p2 != '\0')
{
hash_table[(int)*p2] = 1;
p2++;
}
// 遍歷字符串x
while (*p1 != '\0')
{
// 該字符不需要刪除
if( 0 == hash_table[(int)*p1] )
{
arr1[index]= *p1;
index++;
}
p1++;
}
arr1[index]='\0';
}