1. 程式人生 > >Leetcode中字符串總結

Leetcode中字符串總結

題意 als man 轉換 size kmp algo 返回 時也

本文是個人對LeetCode中字符串類型題目的總結,純屬個人感悟,若有不妥的地方,歡迎指出。

一、有關數字

1、數轉換

題Interger to roman和Roman to integer這兩題是羅馬數字和整數之間的相互轉換,首先要懂得什麽是羅馬數字以及相應的組數規則。LeetCode的題中給出的數字最大的是3999,。針對第一題有兩種解法:第一是列舉出羅馬數字在個十百千上的各種情況,形成一個二維矩陣,然後對整數不停的取余、除10來確定相應的羅馬數字;第二種是先列出羅馬數字組成情況,然後通過從大到小去給定的數字試探。針對第二題,要抓住羅馬數的組詞規則,然後遍歷字符串,若當前值比後一個小,則減去當前值,若不小則加上。

2、計算加、乘

Multiply strings和add binary,前者是兩字符串對應的數字相乘後者是相加,首先這裏肯定會涉及到一個進位的問題,這裏采用的方法是定義一個進位量,進位量的計算是通過與進制數(十進制或二進制)相除得到。這種方法針對鏈表和數組求和也是適用的。針對第一題是定義一個中間變量去保存每次對應的乘積,最後計算進位數,這裏值得註意的有:下標和中間數組的開始的去0操作,這點和String to integer atoi中前處理一樣。第二題要考慮最高位的進位和字符和數字之間的轉換。

3、跳過空格

String to integer atoi這題的思路比較簡單,就是遍歷字符串,保存的結果乘以10加上當前字符對應的數。但有很多需要註意的地方:一是,字符串中的空格問題,若字符串前後有空格,要跳過;二是,字符串中正、負號的問題;三是,字符串的數轉換為整數時,可能越界的問題。這裏針對越界的問題,有兩種解決方法:一是,提升保存結果變量的類型,如變為long long 類;二是,每次乘以10之前先判斷是否乘10之後是否會越界。

Length of last word和上面提到的一點要特別註意,從後面開始遍歷字符串時,要註意跳過空格。

4、驗證數字

valid number判斷給定字符是否是有效數字類型的。這裏針對三種不是數字是合法的情況,第一是字符".",二是字符"e",三是正反號“+”、“-”。其他非數字的字符是非法的。針對這三種情況,也不是所有的出現方式都是合法的。所以本題的關鍵是給出這三種對應的合法情況,針對字符‘e‘,若其出現之前沒有數字出現或是早就有‘e‘出現了,這種情況肯定是非法的,否則,就是合法的,同時更新exp和num,這裏要說明的是num為什麽還是false的?以字符‘‘e‘為分隔去看;針對字符".",之前要是沒有出現"."和“e”,不然是非法的,更新dot為true;對於正負號,出現在字符中間時,若其前一個不是"e"也是非法的。另外開始時肯定要跳過前後的空格

和開始的正負號。

二、最長問題

1、最長回文串

題Longest palindromic substring求出給定字符串中的最長回文子串。首先要明白回文串是什麽---回文串是正反讀起來是一樣的。思路有兩種,一種是暴力解法,遍歷字符串,求出以每個字符為中心的回文串長度,同時維持回文串的最大長度這個變量即可,這裏求以每個字符為中心的回文長度時,要註意回文串有兩種形式:長度是奇數和長度是偶數,此外還要維持一個變量保存最長回文串的起點位置;方法二是Manacher‘s Algorithm算法,可以在線性的時間內求出最大回文串的長度,算法的關鍵在於利用了回文串的特點----關於中心點兩邊相等。該算法分三步:第一步是,改造給定字符串,通過在字符之間插入特定的字符使字符串的長度是奇數個,同時也使得只要出現回文串在改造後的新字符串中都是奇數個;第二步,明白新回文串和原字符回文串中的關系;第三步,求出新字符串中各個字符所對應的回文串長度。另外維持一個最大長度,這樣可以避免再次掃描數組找最大的長度。

2、最長無重復子串

題Longest substring without repeating characters要特別註意的一點是,更新最長無重復子串起點的條件有兩條:當前字符在之前出現過,還有,要在起點之後出現過,怎麽理解第二點了?恩,如:“adbefghba”,當第二個字符b出現時,start移動到第一個字符b處,但移動到第二字符a時,難道因為a出現過一次,就要將起點移動到第一個字符a?顯然不是,所以,出現重復時一定要是在起點之後,才能更新起點。這題最好結合相關代碼理解。

3、最長連續序列

Longest consecutive sequence,還是利用hash表的思想,將字符串存入unordered_set中,然後遍歷字符串,若某字符在hash表中,然後看該字符的左右是否在hash表中,最後右減左,再減1(因為跳出while循環時,兩者都不是和當前字符的相鄰)。另外,我們遍歷到一個字符的左右時,若是刪除了,可避免重復訪問,因為若是現在這個字符和之前的某個字符相鄰,則之前的字符肯定遍歷到了當前字符,所以不必在遍歷一遍。

三、字符串匹配

1、兩字符串是否匹配

Implement strstr,判斷一個是不是另一個的子串,暴力解法是,兩字符串對應的字符一個個對比,直到找個匹配的,這樣的時間復雜度為O(kn)。關鍵的點是不匹配時目標函數的下標的返回。這裏是通過i+j作為目標函數的下標的方式,即可以保證i不動,但目標通過j 的移動,實現對目標串隨對比串的移動;至於KMP算法,就是利用之前對比的信息,來實現快速跳轉對比,從而加速對比過程。

2、表達式匹配

Regular expression matching 關鍵在於當遇到“*”時的處理情況,這裏最好用動態規劃的方法,好理解一些。當前字符不是*時,只要判斷之前對應的是否匹配和當前對應的字符是否匹配即可。當遇到的是*時,*可以代表0個也可代表多個前一個字符,所以要分這兩種情況考慮。

Wildcard matching 若當前字符時*,兩字符當前對應的位相匹配時,則兩者同時向後移動就行,若不匹配則考慮返回上一個*的下一位開始對比,若當前是*,則要記下此時兩個字符串中的位置,所以要定義兩個指針,用於返回比較。

四、找規律

count and say的單次循環中,當當前字符和前一個不相等時,就將字符的個數和對應的字符存入中間變量中,因為下次的初始值是上一次的結果,所以要用每次的結果去做初始值。

Zigzag conversion關鍵在於找到豎行和斜行字符對應下標的關系。以每行為單位去進行。

Simplify path關鍵在於對題意的理解,和采取的思路,這裏兩個"/"之間的字符來判斷操作。

五、哈希

Anagrams以一各個單詞取出來,排序以後插入哈希表中,若遇到已存在哈希表中的字符,則將其對應的原字符串存入結果中,但是對於已經存在哈希表中那個字符對應是否存入,要看是否為第一遇到重復的,可以通過設置,已經存入結果的,將其下標設為-1,每次判斷已在哈希中的字符串的對應下標和-1的大小來決定。這一題可以為好多這類型的題提供思路,要好好理解。

六、深搜

Palindrome partitioning 深搜的套路要好好理解。

Leetcode中字符串總結