小白刷題入門Leetcode(二)——字符串 C++

**

28. 實現 strStr()

解法一:直接用string.fin()函數,只要把返回值不找到的情況搞定就可以。Find函數不找到返回str.npos 這裏改成-1就可以。
這是用語言的內置函數。接下來是別的不用內置函數的實現。

class Solution {
public:
    int strStr(string haystack, string needle) {
        int position=haystack.find(needle); 
        if(position==haystack.npos)return -1;
        else return position;        
    }
};

解法二:雙指針法
用兩個指針,如果匹配,兩個指針就都向右移動,比較下一個字符。如果不匹配, needle的指針重新指向開始,haystack的指針指向剛纔的位置加1;所以用一個start來記錄每次比較的開始位置;
如果用equal函數來比較,每次比較長度爲needle.size()的長度,如果一個字符一個字符的比較,就不需要了;

int strStr(string haystack, string needle) {
    if (needle.empty())return 0;
    if (haystack.empty())return -1;
    int p = 0, q = 0;
    int start = 0;
    while (start < haystack.size())
    {
        for (p = start, q = 0; q < needle.size() && p < haystack.size() ; p++, q++)
        {
            if (!(haystack[p] == needle[q])) break;
            if(q== needle.size()-1)return start;
        }
        start++;
    }
    return -1;
}

答案裏的另一種方法:

class Solution {
public:
    int strStr(string haystack, string needle) {
        if (needle.length() == 0) {
            return 0;
        }
        int len = haystack.length();
        int nlen = needle.length();
        if (len < nlen) {
            return -1;
        }
        int j = 0;
        for (int i = 0; i < len;) {
            if (haystack[i++] == needle[j]) {
                j++;
            } else {
                if (j > 0) {
                    i = i - j;
                    j = 0;
                }
            }
            if (j == nlen) {
                return i - j;
            }
        }
        return -1;
    }
};

3.8 外觀數列

方法一:迭代
用迭代的方法來做,怎麼把這些東西都輸出來呢。一開始n=1得到的是一個爲1的字符串,然後n爲2時,就把連續的數字數出來,num記錄讀到的數字,times記錄次數,第一個字符給num,然後times++,然後與下一個比較。如果相同就指針右移,times++;如果不相同,就把這一組num和times寫進字符串中,把這個字符的值更新給num和times。
直到迭代到了。
這樣需要一個新的字符串來保存結果。
在簡單的題目裏面算是比較難的類型,對string的一些方法的掌握比如to_string()

  string countAndSay(int n) {
        string str1, str2;
        str1 = "1";
        if (n == 1)return str1;
        int i = 1;//用來記錄迭代的次數,直到n-1
        int  times=0, j=0;
        char num;
        for (i = 1; i < n; i++)
        {
            
            for (j = 0; j < str1.size(); j++)
            {
                if (j == 0)
                {
                    num = str1[j];
                    times = 1;
                }
                else {
                    if (str1[j] == num) times++;
                    else {
                        str2+=to_string(times);
                        str2 +=num;
                        num = str1[j];
                        times = 1;
                    }
                }

            }
            str2 += to_string(times);
            str2 += num;
            str1.swap(str2);
            str2.clear();


        }
        return str1;

    }

方法二:看了柳婼https://www.liuchuo.net/archives/4646的博客我覺得這確實是一個簡單題了。

思路大致和上述一致。但是爲什麼不需要清空字符串T的值呢。

#include <iostream>
using namespace std;
int main() {
    string s;
    int n, j;
    cin >> s >> n;
    for (int cnt = 1; cnt < n; cnt++) {
        string t; //每次運行到了這句話T都會變成了空
        for (int i = 0; i < s.length(); i = j) {
            for (j = i; j < s.length() && s[j] == s[i]; j++);
            t += s[i] + to_string(j - i);
        }
        s = t;
    }
    cout << s;
    return 0;
}

58. 最後一個單詞的長度

這個題目的坑在於,可能是一個空格的測試用例,也有可能是末尾一個空格,也有可能是末尾很多空格。
所以我選擇一開始就去除尾巴的空格。
解法一:
第一個循環遍歷這個字符串。第二個for循環找到一個由空格結束的字串。I記錄的其實就是每一個單詞的首地址。
內層循環是爲了找到單詞的尾巴索引。相減就是要得到的字符串大小。

class Solution {
public:
int lengthOfLastWord(string s) {
for (int k = s.size() - 1; k >= 0&& s[k] == ' '; k--) s.pop_back();
    if (s.empty())return 0;
    int j;
    for (int i = 0; i <=s.size(); i=j+1) {
        string t;
        for (j = i; j < s.size()&& s[j] != ' '; j++)  t += s[j];
        if (j == s.size())return j-i;      
        }
        return 666;
    }
};

方法二:
從末尾開始判斷,找到一個不是空格的字符。然後計算這個單詞的大小。

class Solution {
public:
int lengthOfLastWord(string s) {
    for (int k = s.size() - 1; k >= 0&& s[k] == ' '; k--) s.pop_back();
    if (s.empty())return 0;
    int i = 0;
    for ( i = s.size() - 1; i >= 0 && s[i] != ' '; i--);
    return s.size() - i - 1;
    }
};

方法三:
也是從末尾開始找,但是多了一個變量count;在循環中,如果找到了非空格值就count++
否則的話,如果count爲空說明還沒找到倒數第一個單詞,繼續往前找。
Count不爲空說明這是最後一個單詞。

class Solution {
public:
int lengthOfLastWord(string s) {
   int count=0;
   for(int i=s.size()-1;i>=0;i--)
       if(s[i]!=' ')count++;
       else   if(count)return count;
    return count;
    }
};

67. 二進制求和

注意字符和數字相加減得到的值不同。
方法一:
從尾巴開始相加,考慮到兩個串位數不同的情況,用加數num1, num2表示當前的數值。如果一個串遍歷完了,就設爲0;
然後加數對2的餘數放在結果串的開頭,設置進位;
最後注意兩個串都到頭了,如果進位不是0,也要進位在最前面;

class Solution {
public:
    string addBinary(string a, string b) {
        int i = a.size() - 1, j = b.size() - 1,k=0;
        string re;
        int carry = 0;
        int sum = 0;
        int num1 = 0, num2 = 0;
        for (; i >=0 || j >= 0; i--,j--) {
            if (i < 0)num1 = '0';
            else num1 = a[i];
            if (j < 0)num2 = '0';
            else num2 = b[j];
            sum = num1 + num2 + carry-2*'0';
            re.insert(0, to_string(sum % 2));
            carry = sum / 2;

        }
        if (carry) re.insert(0, to_string(carry));
        return re;

    }
};

方法二:
法一的用時比較久,另一種用時最短的算法是位運算。

但是我不會位運算。

用時第二少的算法是沒有太多的加減運算判斷是01 00 10 11這幾種情況。不使用除法和取餘運算,所以設置carry表示進位。

class Solution {
public:
    string addBinary(string a, string b) {
        int k=0;
        string re;
        bool carry = false;
        char ca, cb;
        for (int i = a.size() - 1, j = b.size() - 1; i >= 0 || j >= 0; i--, j--) {
            if (i < 0) ca = '0';
            else ca = a[i];
            if (j < 0)cb = '0';
            else cb = b[j];
            int p = 0;
            if (carry) {
                p++;
                carry = false;
            }
            if ((ca == '0' && cb == '1') || (ca == '1' && cb == '0'))p++;
            if ((ca == '1' && cb == '1'))p += 2;
            if (p > 1) {
                carry = true;
                if (p == 2)p = 0;
                else p=1;
            }
            re.insert(0, to_string(p));
        }
        if(carry) re.insert(0,"1");
        return re;
    }
};

125. 驗證迴文串

給定一個字符串,驗證它是否是迴文串,只考慮字母和數字字符,可以忽略字母的大小寫。

解法一:
頭尾兩個索引,分別找到第一個字母或者數字;然後比較,如果不相等就可以直接返回了。如果相等的話,就要下一步比較。
退出循環的條件是兩個指針相遇;

#include<algorithm>
class Solution {
public:
    bool isPalindrome(string s) {
        if(s.size()<2)return true;        
        transform(s.begin(), s.end(), s.begin(), ::tolower);
        for(int i=0, j=s.size()-1;i<j;i++,j--){
            for(;i<j&&!(s[i]>='a'&&s[i]<='z')&&!(s[i]>='0'&&s[i]<='9');i++)cout<<i<<endl;
            for(;i<j&&!(s[j]>='a'&&s[j]<='z')&&!(s[j]>='0'&&s[j]<='9');j--)cout<<j<<endl;
            if(s[i]!=s[j])return false;            
        }
        return true;
    }
};

解法二:
改進一下,使用C++的isalnum()函數。
transform一次把一整個字符串改爲大寫或者小寫。tolower()一次改一個字符;

#include<algorithm>
class Solution {
public:
    bool isPalindrome(string s) {
        for(int i=0, j=s.size()-1;i<j;i++,j--){
            for(;!isalnum(s[i])&&i<j;i++)cout<<i<<endl;
            for(;!isalnum(s[j])&&i<j;j--)cout<<j<<endl;
            if(tolower(s[i])!=tolower(s[j]))return false;            
        }
        return true;
    }
};

344. 反轉字符串

編寫一個函數,其作用是將輸入的字符串反轉過來。輸入字符串以字符數組 char[] 的形式給出。
不要給另外的數組分配額外的空間,你必須原地修改輸入數組、使用 O(1) 的額外空間解決這一問題。 你可以假設數組中的所有字符都是 ASCII
碼錶中的可打印字符。

解法一:
兩個索引分別指向頭和尾巴,然後這兩個位置的字符交換。直到這兩個索引相遇;

class Solution {
public:
    void reverseString(vector<char>& s) {
        for(int i=0, j=s.size()-1; i<j; j--, i++){
            char c=s[i];
            s[i]=s[j];
            s[j]=c;
        }
            }
};

解法二:
不用第二個索引了,循環跳出的條件變爲i<=N/2, 與N-i-1位置的字符進行交換。這樣處理速度是最快的;

class Solution {
public:
    void reverseString(vector<char>& s) {
        int n=s.size();
        for(int i=0; i<n/2;  i++){
            char c=s[i];
            s[i]=s[n-i-1];
            s[n-i-1]=c;
        }        
    }
};

解法三:
Swap()函數

class Solution {
public:
    void reverseString(vector<char>& s) {
        for(int i=0; i<s.size()/2;  i++)  swap(s[i],s[s.size()-i-1]);               
    }
};

一行搞定;

434. 字符串中的單詞數

方法一:
跳過所有的空格,連在一起的字符記作一個單詞;

class Solution {
public:
    int countSegments(string s) {
        int count=0;
        for(int i=0;i<s.size();){
            while(s[i]==' '&&i<s.size())i++;
            if(i==s.size())return count;
            for(;s[i]!=' '&&i<s.size();i++);
            count++;
        }
        return count;
    }
};

方法二:
一個字符並且後面有一個空格的情況,是一個單詞;
所以一開始在尾巴加一個空格;

class Solution {
public:
    int countSegments(string s) {
        int count=0;
        s+=' ';
        for(int i=0;i< s.size()-1;i++)
            if(s[i]!=' '&&s[i+1]==' ')count++;
        return count;
    }
};

方法三:
用用stringstream。

class Solution {
public:
    int countSegments(string s) {
        int count=0;
        string ss;
        stringstream sss(s);
        for(;sss>>ss;count++);
        return count;
    }
};

在stringstream類中,構造字符串流時,空格會成爲字符串參數的內部分界;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章