力扣 字符串专题

38. 外观数列

https://leetcode-cn.com/problems/count-and-say/

class Solution {
public:
    string countAndSay(int n) {
        string s="1";
        for(int i=2;i<=n;i++){
                string temp="";
            for(int j=0;j<s.size();){
                char n=s[j];
                int num=0;
                while(s[j]==n && j<s.size()){
                    num++;
                    //cout<<num<<endl;
                    j++;
                }
                temp=temp+to_string(num)+n;
                //cout<<temp<<endl;
            }
            s=temp;
        }
        return s;

    }
};

49. 字母异位词分组

https://leetcode-cn.com/problems/group-anagrams/
思路:满足条件的字符串在排序后必相同
可以开一个hash表 第一个映射为排序后的字符串,第二个为原字符串
映射完毕输出即可

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string,vector<string>> hash;
        for(auto s:strs){
            string temp=s;
            sort(s.begin(),s.end());
            hash[s].push_back(temp);
        }
        vector<vector<string>> res;
        for(auto s:hash){
            res.push_back(s.second);
        }
        return res;
    }
};

151. 翻转字符串里的单词

https://leetcode-cn.com/problems/reverse-words-in-a-string/

class Solution {
public:
    string reverseWords(string s) {
        int k=0;
        for(int i=0;i<s.size();){
            int j=i;
            while(s[j]==' '&&j<s.size()) j++;
            if(j==s.size()) break;
            i=j;
            while(s[j]!=' '&&j<s.size()) j++;
            reverse(s.begin()+i,s.begin()+j);
            if(k) s[k++]=' ';
            while(i<j) s[k++]=s[i++];
        }
        s.erase(s.begin()+k,s.end());
        reverse(s.begin(),s.end());
        return s;

    }
};

165. 比较版本号

https://leetcode-cn.com/problems/compare-version-numbers/


class Solution {
public:
    vector<int> fun(string ver){
        //将每一个版本的数字压入vector
        vector<int> ans;
        for(int i=0;i<ver.size();){
            int j=i;
            int s=0;
            while(j<ver.size() && ver[j]!='.'){
                s=s*10+ver[j]-'0';
                j++;
            }
            i=j+1;
            ans.push_back(s);
        }
        //删除后端0 如1.0和1.0.0 后面的0不影响大小
        //但是如果不删除 vector比较会出问题
        while(ans.size() && ans.back()==0) {
            ans.pop_back();
        }
        return ans;
    }
    int compareVersion(string version1, string version2) {
        auto n1=fun(version1);
        auto n2=fun(version2);
        if(n1>n2) return 1;
        else if(n1==n2) return 0;
        else {
            return -1;
        }
    }
};


3. 无重复字符的最长子串

https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

总结:这个思路主要还是和双指针基本思路一致:固定一段,另外一端只要满足条件就继续往前.不满足就让不动的一段移动

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char, int> hash;
        int res = 0;
        for (int i = 0, j = 0; j < s.size(); j ++ )
        {
            hash[s[j]] ++ ;
            while (hash[s[j]] > 1) hash[s[i ++ ]] -- ;
            res = max(res, j - i + 1);
        }
        return res;
    }
};


166. 分数到小数

https://leetcode-cn.com/problems/fraction-to-recurring-decimal/
计算小数部分的难点在于如何判断是否是循环小数,以及找出循环节的位置。
回忆手工计算除法的过程,每次将余数乘10再除以除数,当同一个余数出现两次时,我们就找到了循环节。
所以我们可以用一个哈希表 unordered_map<int,int> 记录所有余数所对应的商在小数点后第几位,当计算到相同的余数时,上一次余数的位置和当前位置之间的数,就是该小数的循环节。

时间复杂度分析:计算量与结果长度成正比,是线性的。所以时间复杂度是 O(n)。

class Solution {
public:
    string fractionToDecimal(int numerator, int denominator) {
        long long n=numerator,d=denominator;
        bool minus=false;
        //处理负数情况
        if(n<0) minus=!minus,n=-n;
        if(d<0) minus=!minus,d=-d;
        string res=to_string(n/d);
         n=n%d;
        //无小数情况
        if(n==0){
            if(minus&&res!="0") return '-'+res;
            else return res;
        }
        res+='.';
        unordered_map<long long, int> hash;
        while(n){
            if(hash[n]){
                res=res.substr(0,hash[n])+'('+res.substr(hash[n])+')';
                break;
            }
            else hash[n]=res.size();
            n*=10;
            res+=to_string(n/d);
            n%=d;
        }
        if(minus) res='-'+res;
        return res;
    }
};

  1. 实现 Trie (前缀树)
    https://leetcode-cn.com/problems/implement-trie-prefix-tree/
    Trie树例图:

    被打上标记的尾结尾符号,此图保存的单词有:a,abc,bac,bbc,ca
class Trie {
public:
    struct  Node{
        bool is_end;//标记是否结尾
        Node *next[26];
        Node(){
            is_end=false;
            for(int i=0;i<26;i++){
                next[i]=0;
            }
        }
    };
    Node *root;
    /** Initialize your data structure here. */
    Trie() {
        root=new Node();
    }

    /** Inserts a word into the trie. */
    void insert(string word) {
        Node *p=root;
        for(char c : word){
            int son=c-'a';
            if(!p->next[son]) p->next[son]=new Node();
            p=p->next[son];
        }
        p->is_end=true;
    }

    /** Returns if the word is in the trie. */
    bool search(string word) {
        Node *p=root;
        for(char c:word){
            int son=c-'a';
            if(p->next[son]) p=p->next[son];
            else return false;
        }
        return p->is_end;
    }
//返回trie中是否有以给定前缀开头的单词。
//将上面函数最后判断是否是结尾修改即可
    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix) {
        Node *p=root;
        for(char c: prefix){
            int son=c-'a';
            if(p->next[son]) p=p->next[son];
            else return false;
        }
        return true;
    }
};

/**
 * Your Trie object will be instantiated and called as such:
 * Trie* obj = new Trie();
 * obj->insert(word);
 * bool param_2 = obj->search(word);
 * bool param_3 = obj->startsWith(prefix);
 */

  1. 分割回文串
    https://leetcode-cn.com/problems/palindrome-partitioning/
class Solution {
public:
    vector<vector<string>> ans;//答案
    vector<string> path;//当前选择
    bool check(string &now)//检查是不是回文串
    {
        if(now.empty()) return false;
        for(int i = 0, j = now.size() - 1; i < j; i ++, j --)
            if(now[i] != now[j])
                return false;
        return true;
    }
    vector<vector<string>> partition(string s) {
        dfs("", 0, s);
        return ans;
    }
    void dfs(string now,int u,string &s){
        if (u == s.size())
        {
            if (check(now))
            {
                path.push_back(now);
                ans.push_back(path);
                path.pop_back();
            }
            return;
        }

        if (check(now))
        {
            path.push_back(now);
            dfs("", u, s);
            path.pop_back();
        }
        dfs(now + s[u], u + 1, s);
    }
};

posted @ 2021-03-16 12:38  一个经常掉线的人  阅读(119)  评论(0)    收藏  举报