(0001)刪除字符串中的公共字符

(0001)刪除字符串中的公共字符

題目: 輸入兩個字符串, 從第一字符串(下文稱爲x)中刪除第二個字符串(下文簡稱爲y)中所有的字符. 例如, 輸入They are students.aeiou, 則刪除之後的第一個字符串變成Thy r stdnts.

解題思路

最簡單的思路

兩層循環遍歷, 每遍歷到字符串 y 中的一個字符, 就在字符串 x 中找到相同的字符, 找到之後刪除它,並將字符串 x 後面的字符整體向前移動1位。所以這個過程的時間複雜度是O(n³).

優化 - 解決順序存儲結構中刪除後整體移動的問題

刪除一個字符的另一個思路是: 不是某個指定的字符就保留, 按照這種思維方式, 可以將需要保留的字符覆蓋在原來的字符串上, 此時需要兩個標記變量(或者說指針), 一個用於控制字符串 x 的整體遍歷過程,一個記錄要覆蓋的位置, 這樣的話,我們就能避免每一次刪除後的整體平移,時間複雜度優化爲O(n²), 如下圖所示.

在這裏插入圖片描述


優化 - 引入hash表, 避免雙層遍歷

  1. O(n²)的時間複雜度是由遍歷兩個字符串產生的,引入hash表能夠避免循環嵌套的問題,我採用的方式是對字符串 y, 建立一個hash表, 在字符串 y 中出現的字符, 在hash表中的值爲1, 反之爲0.
  2. 參考標點符號和字母的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';
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章