LeetCode刷题日记(Day4)— String

这篇博客详细记录了作者在LeetCode上遇到的字符串相关题目,包括Sunday字符串匹配算法,最长公共前缀,字符串最后一个单词的长度,首次出现的唯一字符,赎金信问题,字符串反转等。作者分享了各种解题思路,如暴力检查、Trie树、计数器等,并探讨了优化方法,如使用数组代替unordered_map,以及Python正则表达式的巧妙应用。
摘要由CSDN通过智能技术生成

LeetCode 28. Implement strStr()

int strStr(string haystack, string needle) {
    const int max_num = 1024;
    int shift[max_num];
    int n = haystack.size(), m = needle.size();

    for(int i = 0; i < max_num; i++)
        shift[needle[i]] = m + 1;

    for(int i = 0; i < m; i++)
        shift[needle[i]] = m - i;

    int s = 0, j = 0;
    while(s <= n - m) {
        j = 0;
        while(haystack[s+j] == needle[j]) {
            j++;
            if(j >= m)
                return s;
        }
        s += shift[haystack[s+m]];
    }
    return -1;
}

Sunday字符串匹配算法,参考博客:字符串匹配——Sunday算法

int strStr(string haystack, string needle) {
    return haystack.find(needle);
}

搞事情的一行代码版本 -.-

 

LeetCode 14. Longest Common Prefix

string longestCommonPrefix(vector<string>& strs) {
    if(strs.size() == 0) return "";
    
    int pre_index = -1;
    bool flag = true;
    for(int i = 0; i < strs[0].size(); i++) {
        for(int j = 1; j < strs.size(); j++)
            if(strs[j][i] != strs[0][i])
                flag = false;
        if(flag) pre_index = i;
        else break;
    }
    
    string res = "";
    for(int i = 0; i <= pre_index; i++)
        res += strs[0][i];
    return res;
}

思路:暴力检查,注意空值即可,时间复杂度 O(nk)。

另一种思路是Tire树,建树后检查最小的深度,比较麻烦且效率不高。

 

LeetCode 58. Length of Last Word

int lengthOfLastWord(string s) {
    int index = s.size() - 1, len = 0;
    while(index >= 0 && s[index] == ' ')
        index--;
    while(index >= 0 && s[index] != ' ')
        index--,len++;
    return len;
}

思路:反向检查,注意 1.末尾可能有多余的空格,2.字符串中无空格,3.字符串全部是空格,4.字符串为空 等可能的特殊情况即可。

 

LeetCode 387. First Unique Character in a String

int firstUniqChar(string s) {
    int counter[26] = {0};
    vector<char> vec;
    for(int i = 0; i < 26; i++)
        counter[i] = -1;
    for(int i = 0; i < s.size(); i++)
        vec.push_back(s[i]);
    
    for(int i = 0; i < s.size(); i++)
        if(counter[s[i]-'a'] == -1)
            counter[s[i]-'a'] = i;
        else if(counter[s[i]-'a'] >= 0)
            counter[s[i]-'a'] = -2;
    
    for(int i = 0; i < vec.size(); i++)
        if(counter[vec[i]-'a'] >= 0)
            return counter[vec[i]-'a'];
    return -1;
}

思路:计数器,初始化为-1,遍历字符,若计数器中为-1,则将下标添加进去,否则标记为-2(有重复的),使用一个vector来记录顺序。

int firstUniqChar(string s) {
    int counter[26] = {0};
    
    for(int i = 0; i < s.size(); i++)
        counter[s[i]-'a']++;
    
    for(int i = 0; i < s.size(); i++)
        if(counter[s[i]-'a'] == 1)
            return i;
            
    return -1;
}

改进的方法:使用原有的字符串的顺序,而不是自己创建一个vector。看起来是我的思路被局限了呢2333

 

LeetCode 383.Ransom Note

bool canConstruct(string ransomNote, string magazine) {
    unordered_map<int, int> ran_m, mag_m;
    for(int i = 0; i < ransomNote.size(); i++)
        ran_m[ransomNote[i]]++;
    for(int i = 0; i < magazine.size(); i++)
        mag_m[magazine[i]]++;
    for(auto iter = ran_m.begin(); iter != ran_m.end(); ++iter)
        if(iter->second > mag_m[iter->first])
            return false;
    return true;
}

思路:我想到的办法是使用计数器进行计数,之后再检查。

bool canConstruct(string ransomNote, string magazine) {
    int counter[26] = {0};
    for(int i = 0; i < magazine.size(); i++)
        counter[magazine[i]-'a']++;
    for(int i = 0; i < ransomNote.size(); i++)
        if(--counter[ransomNote[i]-'a'] < 0)
            return false;
    return true;
}

讨论区发现的改进方法:使用数组代替unordered_map,时间从40ms减少到20ms

 

LeetCode 344. Reverse String

void reverseString(vector<char>& s) {
    int start = 0, end = s.size() - 1;
    while(start < end) {
        swap(s[start], s[end]);
        start++, end--;
    }
}

一行代码版本:

void reverseString(vector<char>& s) {
    reverse(s.begin(), s.end());
}

 

LeetCode 151.Reverse Words in a String

void reverseWords(string &s) {
    bool flag = true;
    for(int i = 0; i < s.size(); i++)
        if(s[i] != ' ')
            flag = false;
    if(flag == true) {
        s = "";
        return ;
    }
    string str = "";
    stack<string> st;
    int len = s.size();
    for(int i = 0; i < len; i++){
        if(s[i] == ' '){
            if(str != "" && str != " ")
                st.push(str);
            str = "";
        }
        else
            str += s[i];
    }
    if(str != "" && str != " ")
        st.push(str);
    str = "";
    while(!st.empty()) {
        str += st.top();
        st.pop();
        if(!st.empty())
            str += ' ';
    }
    s = str;
}

流氓题目,养成看题的好习惯qwq

 

LeetCode 557. Reverse Words in a String III

string reverseWords(string s) {
    int start = 0, end = 0;
    while(start < s.size()) {
        while(start < s.size() && s[start] == ' ')
            start++;
        end = start;
        while(end < s.size() && s[end] != ' ')
            end++;
        reverse(s.begin()+start, s.begin()+end);
        start = end;
    }
    return s;
}

思路:获取每个单词的首尾位置,反转。

 

LeetCode 345. Reverse Vowels of a String

bool isVowels(char c) {
    if(c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u')
        return true;
    if(c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U')
        return true;
    return false;
}
string reverseVowels(string s) {
    int start = 0, end = s.size() - 1;
    while(start < end) {
        while(start < s.size() && !isVowels(s[start]))
            start++;
        while(end < s.size() && !isVowels(s[end]))
            end--;
        if(start < end)
            swap(s[start], s[end]);
        start++, end--;
    }
    return s;
}

思路:找到每个元音字母的位置后反转,注意判断,还有大小写都是要考虑的emmm

def reverseVowels(self, s):
    vowels = re.findall('(?i)[aeiou]', s)
    return re.sub('(?i)[aeiou]', lambda m: vowels.pop(), s)

跑个题:在评论区看到的使用Python正则表达式的写法,niubi

 

LeetCode 205. Isomorphic Strings

bool isIsomorphic(string s, string t) {
    unordered_map<char, char> s_t, t_s;
    for(int i = 0; i < s.size(); i++)
        if(s_t[s[i]] == 0 && t_s[t[i]] == 0) {
            s_t[s[i]] = t[i];
            t_s[t[i]] = s[i];
        }
        else if(s_t[s[i]] != t[i])
            return false;
    return true;
}

思路:建立相互映射的Hash表,检查是否匹配,使用数组代替unordered_map速度会略快一些。

 

LeetCode 290. Word Pattern

bool wordPattern(string pattern, string str) {
    vector<string> words;
    stringstream ss(str);
    while(ss >> str)
        words.push_back(str);

    if(pattern.size() != words.size()) return false;

    unordered_map<char, string> p_s;
    unordered_map<string, char> s_p;

    for(int i = 0; i < pattern.size(); i++)
        if(p_s[pattern[i]] == "" && s_p[words[i]] == 0) {
            p_s[pattern[i]] = words[i];
            s_p[words[i]] = pattern[i];
        }
        else if(p_s[pattern[i]] != words[i])
            return false;

    return true;
}

思路:同上一题,这次貌似无法用数组优化了2333

 

LeetCode 242. Valid Anagram

bool isAnagram(string s, string t) {
    if(s.size() != t.size()) return false;
    int counter[26] = {0};
    for(int i = 0; i < s.size(); i++)
        counter[s[i]-'a']++;
    for(int i = 0; i < t.size(); i++)
        if(--counter[t[i]-'a'] < 0)
            return false;
    return true;
}

思路:计数器A上去就完事了

 

LeetCode 49. Group Anagrams

vector<vector<string>> groupAnagrams(vector<string>& strs) {
    unordered_map<string, vector<string>> map;

    for(const auto& str : strs){
        string s = str;
        sort(begin(s), end(s));
        map[s].push_back(move(str));
    }

    vector<vector<string>> result;
    for(auto& kv : map)
        result.push_back(move(kv.second));

    return result;
}

思路:还是hash表,可以考虑计算Hash值而不是对字符串进行排序,思路是使用26个素数,对一个字符串中的字符对应的素数进行连乘。

参考思路:Java beat 100%!!! use prime number

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值