日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

cstring判断包含字符串_作为java程序员要知道的大厂常见的算法面试题:字符串的包含...

發(fā)布時間:2024/7/19 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 cstring判断包含字符串_作为java程序员要知道的大厂常见的算法面试题:字符串的包含... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1.2 字符串的包含

題目描述

給定一長字符串a(chǎn)和一短字符串b。請問,如何最快地判斷出短字符串b中的所有字符是否都在長字符串a(chǎn)中?請編寫函數(shù)bool StringContain(string &a, string &b)實現(xiàn)此功能。

為簡單起見,假設輸入的字符串只包含大寫英文字母。下面舉幾個例子。

  • 如果字符串a(chǎn)是"ABCD",字符串b是"BAD",答案是true,因為字符串b中的字母都在字符串a(chǎn)中,或者說b是a的真子集。
  • 如果字符串a(chǎn)是"ABCD",字符串b是"BCE",答案是false,因為字符串b中的字母E不在字符串a(chǎn)中。
  • 如果字符串a(chǎn)是"ABCD",字符串b是"AA",答案是true,因為字符串b中的字母A包含在字符串a(chǎn)中。

分析與解法

此題初看似乎很簡單,但要高效地實現(xiàn)并不輕松。而且,如果面試官步步緊逼,一個一個否決你想到的方法,要求你給出更快、更好的方案,恐怕就要費不少腦筋了。

解法一:蠻力輪詢

判斷短字符串b中的字符是否都在長字符串a(chǎn)中,最直觀也是最簡單的思路則是:輪詢短字符串b中的每一個字符,逐個與長字符串a(chǎn)中的每個字符進行比較,看是否都在字符串a(chǎn)中。

參考代碼如下:

bool StringContain(string &a, string &b) {for (int i = 0; i < b.length(); ++i){int j;for (j = 0; (j < a.length()) && (a[j] != b[i]); ++j);if (j >= a.length()){return false;}}return true; }

如果n是長字符串a(chǎn)的長度,m是短字符串b的長度,那么此算法需要O(nm)次比較。顯然,如果n和m很大,時間開銷太大,需要尋找更好的辦法。

解法二:排序后輪詢

如果允許排序,可以考慮先排序后輪詢。例如,可先對這兩個字符串中的字母進行排序,然后再對兩個字符串依次輪詢。

常規(guī)情況下,兩個字符串的排序需要O(mlogm)+O(nlogn)次操作,之后的線性掃描需要O(m+n)次操作。關于排序方法,可以采用最常用的快速排序。

參考代碼如下:

bool StringContain(string &a, string &b) {sort(a.begin(), a.end());sort(b.begin(), b.end());for (int pa = 0, pb = 0; pb < b.length();){while ((pa < a.length()) && (a[pa] < b[pb])){++pa;}if ((pa >= a.length()) || (a[pa] > b[pb])){return false;}++pb;}return true; }

解法三:素數(shù)相乘

有沒有比排序后輪詢更好的方法呢?

首先,讓長字符串a(chǎn)中的每個字母與一個素數(shù)對應,如A對應2,B對應3,C對應5,……,依次類推。再遍歷長字符串a(chǎn),把a中的每個字母對應的素數(shù)相乘,得到一個整數(shù)。然后,讓短字符串b中的字母也對應相應的素數(shù),再用b中的每個字母對應的素數(shù)除上面得到的整數(shù)。如果結果有余數(shù),說明結果為false,當即退出程序;如果整個過程中沒有余數(shù),則說明短字符串b是長字符串a(chǎn)的子集。

具體思路總結如下。

(1)按照從小到大的順序,用26個素數(shù)分別代替長字符串a(chǎn)中的所有字母。

(2)遍歷長字符串a(chǎn),求得a中的所有字母對應的素數(shù)的乘積。

(3)遍歷短字符串b,判斷上一步得到的乘積能否被b中的字母對應的素數(shù)整除。

(4)輸出結果。

上述算法的時間復雜度為O(m+n)。當然,最好情況下的時間復雜度為O(n),即在遍歷短字符串b的第一個字母,與長字符串a(chǎn)中所有字符所對應的素數(shù)的乘積相除時,當即出現(xiàn)余數(shù),便直接退出程序,返回false。

bool StringContain(string &a, string &b) {const int p[26] = { 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 f = 1;for (int i = 0; i < a.length(); ++i){int x = p[a[i] - 'A'];if (f % x){f *= x;}}for (int i = 0; i < b.length(); ++i){int x = p[b[i] - 'A'];if (f % x){return false;}}return true; }

這種素數(shù)相乘的方法看似可行,實則不可行,因為素數(shù)相乘的結果會很大,從而導致整數(shù)溢出(前16個字母對應的素數(shù)相乘便會超出long long類型所能表示的最大整數(shù)范圍)。

解法四:位運算法

如果面試官繼續(xù)追問,到底有沒有更好的辦法呢?或許你絞盡腦汁能想到計數(shù)排序。但除了計數(shù)排序還有別的辦法嗎?

事實上,可以先把長字符串a(chǎn)中的所有字符都放入一個散列表(hash table)中,然后輪詢短字符串b,看b中的每個字符是否都在散列表里,如果都在,說明長字符串a(chǎn)包含短字符串b;否則,說明不包含。

再進一步,可以用位運算(26位整數(shù)表示)為長字符串a(chǎn)計算出一個“簽名”,再逐一將短字符串b中的字符放到a中進行查找。

參考代碼如下:

bool StringContain(string &a, string &b) {int hash = 0;for (int i = 0; i < a.length(); ++i){hash |= (1 << (a[i] - 'A'));}for (int i = 0; i < b.length(); ++i){if ((hash & (1 << (b[i] - 'A'))) == 0){return false;}}return true; }

這個位運算方法的實質是用一個整數(shù)代替了散列表,它的空間復雜度為O(1),時間復雜度為O(n+m)。至此,算是比較完美地解決了這個字符串包含的問題。

但是,這樣真的完美了嗎?請讀者繼續(xù)思考。

舉一反三

變位詞

如果兩個字符串中的字符一樣,出現(xiàn)次數(shù)也一樣,只是出現(xiàn)的順序不一樣,則認為這兩個字符串是兄弟字符串。例如,"bad"和"adb"即為兄弟字符串。現(xiàn)提供一個字符串,請問如何在字典中迅速找到它的兄弟字符串?

END

資料分享:

工作一到五年的程序員朋友面對目前的技術無從下手,感到很迷茫,高清思維導圖及相關視頻資料獲取方式關注+轉發(fā)+私信【架構】里面有阿里Java高級大牛直播講解知識點,分享知識,課程內容都是各位老師多年工作經(jīng)驗的梳理和總結,帶著大家全面、科學地建立自己的技術體系和技術認知!

精講直播課:

全面知識點分析:

豐富資料:

總結

以上是生活随笔為你收集整理的cstring判断包含字符串_作为java程序员要知道的大厂常见的算法面试题:字符串的包含...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。