LeetCode题解之字符串(一)

176 阅读2分钟

剑指offer很多题都是数字类的和字符串的,太麻烦了...

8. 字符串转换整数 (atoi)

class Solution {
public:
    int myAtoi(string str) {
        if(!str.size()) return 0;
        int n = str.size();
        bool is_neg = false;
        long long res = 0;
        int i = 0;
        for(; i < n; i ++) 
            if(str[i] == ' ') continue;
            else break;
        if(str[i] == '-') {is_neg = true; i ++;}
        else if(str[i] == '+') i ++;
        for(int j = i; j < str.size() && str[i]>='0' && str[i]<='9'; j ++)
        {
            if(is_neg) res = res*10 - (str[i]-'0');//因为需要在溢出时考虑正负,所以直接在循环时把正负号分开考虑
            else res = res*10 + (str[i]-'0');
            if(res > INT_MAX ) {return INT_MAX;}
            if(res < INT_MIN) {return INT_MIN;}
            i++;
        }
        return res;
    }
};

12. 整数转罗马数字

class Solution {
public:
    string intToRoman(int num) {
        if(num <= 0) return "";
        string res = "";
        int number[13] = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
        string flags[13] = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
        for(int i = 0; i < 13; i ++)
        {
            if(num < number[i]) continue;
            while(num >= number[i])
            {
                res += flags[i];
                num -= number[i];
            }
        }
        return res;
    }
};

13. 罗马数字转整数

class Solution {
public:
    int romanToInt(string s) {
        map<char,int>  m = {{'I',1},{'V',5},{'X',10},{'L',50},{'C',100},{'D',500},{'M',1000}};//hash表
        int res = 0;
        //如果前一个数比后一个小,就减去,其余都直接加上
        for(int i = 0; s[i]; i ++)
        {
            if(i + 1 < s.size() && m[s[i]] < m[s[i + 1]]) res -= m[s[i]];
            else res += m[s[i]];
        }
        return res;
    }
};

14. 最长公共前缀

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        if(!strs.size()) return "";
        int n = strs.size();
        for(int i = 0; i < strs[0].size(); i ++)
        {
            char tmp = strs[0][i];//tmp直接在第一个数里面取,假设最长前缀就是strs[0],因为不管怎么不会超过其中任何一个的长度,后面循环遇到不满足的再跳出
            for(int j = 1; j < n; j ++)
            {//1.遇到其中最短长度了,0~i-1共i个数是可以的;2.遇到不等于的情况了,0~i-1共i个数是可以的
                if(i == strs[j].size() || strs[j][i] != tmp ) return strs[0].substr(0, i);
            }
        }
        return strs[0];
            
    }
};

17. 电话号码的字母组合

class Solution {
public:
    string chars[8] = {"abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
    vector<string> letterCombinations(string digits) {
        //用循环实现搜索
        if(digits.empty()) return vector<string>();
        vector<string> state(1, "");
        for(auto u : digits)
        {
            vector<string> now;
            for(auto x : chars[u - '2'])//取出abc中的 a b c
                for(auto s : state)//加在前面所有状态里
                    now.push_back(s + x);
            state = now;
        }
        return state;
    }
};

剑指 Offer 05. 替换空格

class Solution {
public:
    string replaceSpace(string s) {
        int len = s.size();
        int cnt = 0;
        for(int i = 0; i < len; i ++) if(s[i] == ' ') cnt ++;
        int N = 2 * cnt;
        string s2(N, ' ');
        s += s2;
        for(int i = len + N - 1,j = len - 1; j >= 0; i --, j --)
        {
            if(s[j] != ' ') s[i] = s[j];
            else
            {
                s[i] = '0', s[-- i] = '2',s[-- i] = '%';
            }
        }
        return s;
    }
};

剑指 Offer 58 - II. 左旋转字符串

class Solution {
public:
    string reverseLeftWords(string s, int n) {
        string res;
        for(int i = 0; i < n; i ++) res += s[i];
        s.erase(0, n);
        s += res;
        return s;
    }
};

剑指 Offer 58 - I. 翻转单词顺序

class Solution {
public:
    string reverseWords(string s) {
        //不开新空间,用o(n)时间和o(1)空间
        //先删除前后空格
        int k = 0, n = s.size(), e = n-1;
        while(k < s.size() && s[k] == ' ') k++; // 去掉前面的空格
        while(e >= 0 && s[e] == ' ') e--; // 去掉后面的空格
        s.erase(e + 1, n - e - 1);//先删后面的空格再删前面,免得前面影响序号
        s.erase(0, k);
        //去掉中间空格
        int siz = s.size();
        for(int i = 0; i < siz; i ++)
        {
            int j = i;
            while(s[i] == ' ' && i < siz) i++;
            //两个及以上的空格
            if(i > (j + 1) && i < siz) s.erase(j + 1, i - j - 1), siz = siz - (i - j - 1),i = j;
        }
        //1.翻转整个句子
        //2.每个单词内部翻转
        reverse(s.begin(), s.end());
        for(int i = 0; i < s.size(); i ++)
        {
            int j = i;
            while(s[j] !=' ' && j < s.size()) j ++;
            reverse(s.begin() + i, s.begin() + j);
            i = j;
        }
        return s;
     }
   
};

剑指 Offer 20. 表示数值的字符串

class Solution {
public:
    bool isNumber(string s) {
        //去除前后空格
        int i = 0;
        while (i < s.size() && s[i] == ' ') i ++ ;
        int j = s.size() - 1;
        while (j >= 0 && s[j] == ' ') j -- ;
        if (i > j) return false;
        s = s.substr(i, j - i + 1);
        //处理+-.
        if(s[0] == '+' || s[0] == '-') s = s.substr(1);//直接到末尾子串
        if(s.empty() || (s[0] == '.' && s.size() == 1)) return false;//+-.的情况
        
        //遍历
        int dot = 0,e = 0;//统计这两个值
        for(int i = 0; i < s.size(); i ++)
        {
            if (s[i] >= '0' && s[i] <= '9');
            else if (s[i] == '.')//如果是.,则前面不能有e,点的个数不能>1
            {
                dot ++ ;
                if (e || dot > 1) return false;
            }
            else if (s[i] == 'e' || s[i] == 'E')//如果是e,不能是最后一个字符或者第一个字符,或者在.后面的.e情况,或者e+ e-是最后两个字符的情况
            {
                e ++ ;
                if (i + 1 == s.size() || !i || e > 1 || i == 1 && s[0] == '.') return false;
                if (s[i + 1] == '+' || s[i + 1] == '-')//e
                {
                    if (i + 2 == s.size()) return false;
                    i ++ ;
                }
            }
            else return false;
        }
        return true;
    }
};