字符串比较

165.比较版本号

这一题说实话想得复杂了,将一段纯数字字符串转换为正确的数字类型,只需要采取进位相加的方式就行了。一段确定一个数字

  1. class Solution {
  2. public:
  3. int compareVersion(string version1, string version2) {
  4. int n = version1.size(), m = version2.size();
  5. int i = 0, j = 0;
  6. while(i < n || j < m){
  7. int num1 = 0;
  8. for(; i < n &&version1[i] != '.'; i++){
  9. num1 = num1*10 + version1[i] - '0';
  10. }
  11. i++;
  12. int num2 = 0;
  13. for(; j < m&&version2[j] != '.'; j++){
  14. num2 = num2*10 + version2[j] - '0';
  15. }
  16. j++;
  17. if(num1 != num2){
  18. return num1 > num2 ? 1 : -1;
  19. }
  20. }
  21. return 0;
  22. }
  23. };

242. 有效的字母异位词(数组存储频率)、

  1. class Solution {
  2. public:
  3. bool isAnagram(string s, string t) {
  4. if(s.size() != t.size())
  5. return false;
  6. vector<int> count(26);
  7. for(int i = 0; i < s.size(); i++){
  8. count[s[i] - 'a']++;
  9. count[t[i] - 'a']--;
  10. }
  11. for(int i = 0; i < 25; i++){
  12. if(count[i] != 0)
  13. return false;
  14. }
  15. return true;
  16. }
  17. };

205. 同构字符串(数组)

  • 也是用数组解决的
  • 记录两个字符串每个位置的字符第一次出现的位置,如果两个字符串中相同位置的字符与它们第一次出现的位置一样,那么这两个字符串同构。

    1. class Solution {
    2. public:
    3. bool isIsomorphic(string s, string t) {
    4. vector<int> first1(128,0),first2(128, 0);
    5. for(int i = 0; i < s.length(); i ++){
    6. if(first1[s[i]] != first2[t[i]])
    7. return false;
    8. first1[s[i]] = first2[t[i]] = i + 1;//能走到这一步就代表前面的等式也成立了。
    9. }
    10. return true;
    11. }
    12. };

    696. 计数二进制子串

  • 使用pre来记录前一个元素出现的次数,cur记录当前元素出现的次数

  • 每次当pre大于或者等于前面元素出现的次数时,就记录下来

    1. class Solution {
    2. public:
    3. int countBinarySubstrings(string s) {
    4. int pre = 0, cur = 1, count = 0;
    5. for(int i = 1; i < s.size(); i++){
    6. if(s[i] == s[i-1]){
    7. ++cur;
    8. } else {
    9. pre = cur;
    10. cur = 1;
    11. }
    12. if(pre >= cur){
    13. ++count;
    14. }
    15. }
    16. return count;
    17. }
    18. };

    3. 无重复字符的最长子串(哈希表+滑动窗口)

  • 简单哈希表,使用滑动窗口维护,哈希表的所有值都不能大于1

    1. class Solution {
    2. public:
    3. int lengthOfLongestSubstring(string s) {
    4. int n = s.size(), ans = 0;
    5. if(n<2){
    6. return n;
    7. }
    8. unordered_map<char, int> hash;
    9. for(int i = 0, j = 0; i < n; i++){
    10. hash[s[i]]++;
    11. while(hash[s[i]]!=1&&j<i){
    12. hash[s[j]]--;
    13. j++;
    14. }
    15. ans = max(ans, i-j+1);
    16. }
    17. return ans;
    18. }
    19. };

    字符串理解

    227. 基本计算器 II(经典)

  • 可以在字符串前面增加一个+号,然后将字符串分割成(运算符, 数字)形式,这样就可以从左往右处理了,

  • 由于乘除的优先级高于加减,因此我们需要使用一个中间变量来存储高优先度的运算。
  • 这里还需要考虑到两个连在一起的数字
  1. class Solution {
  2. public:
  3. int calculate(string s) {
  4. vector<int> stk;
  5. char preSign = '+';
  6. int num = 0;
  7. int n = s.length();
  8. for (int i = 0; i < n; ++i) {
  9. if (isdigit(s[i])) {//判断s[i]是不是数字
  10. num = num * 10 + int(s[i] - '0');//这里是计算多位数的情况
  11. }
  12. if (!isdigit(s[i]) && s[i] != ' ' || i == n - 1) {//如果是运算符,或者是最后一位,则计算num
  13. //千万注意,这里的运算符使用的是上一次的运算符
  14. switch (preSign) {
  15. case '+':
  16. stk.push_back(num);
  17. break;
  18. case '-':
  19. stk.push_back(-num);
  20. break;
  21. case '*':
  22. stk.back() *= num;//这里因为乘法有优先级
  23. break;
  24. default:
  25. stk.back() /= num;//出发也是一样。
  26. }
  27. preSign = s[i];//前一个符号
  28. num = 0;//当遇到一个符号之后前一个num置零
  29. }
  30. }
  31. return accumulate(stk.begin(), stk.end(), 0);
  32. }
  33. };
  34. //想法很好,如果是加号则直接入栈,减号则加负号入栈,乘除都是先计算后入栈、

409. 最长回文串(哈希表)

  1. class Solution {
  2. public:
  3. int longestPalindrome(string s) {
  4. int n = s.size(), ans = 0;
  5. unordered_map<char, int> hash;
  6. for(auto it : s){
  7. hash[it]++;
  8. }
  9. for(auto it: hash){
  10. if(it.second%2==0){
  11. ans+=it.second;
  12. } else {
  13. ans+=it.second-1;
  14. }
  15. }
  16. return ans<n? ans+1:ans;
  17. }
  18. };

522. 最长特殊序列 II(脑筋急转弯)

  1. class Solution {
  2. public:
  3. int findLUSlength(vector<string>& strs) {
  4. auto is_subseq = [](const string& s, const string& t) -> bool {
  5. int pt_s = 0, pt_t = 0;
  6. while (pt_s < s.size() && pt_t < t.size()) {
  7. if (s[pt_s] == t[pt_t]) {
  8. ++pt_s;
  9. }
  10. ++pt_t;
  11. }
  12. return pt_s == s.size();
  13. };
  14. int n = strs.size();
  15. int ans = -1;
  16. for (int i = 0; i < n; ++i) {
  17. bool check = true;
  18. for (int j = 0; j < n; ++j) {
  19. if (i != j && is_subseq(strs[i], strs[j])) {//如果当前字符串不是其他任意字符串的子串,则一定为特殊字符串。因为如果子串是特殊字符串,那么当前字符串也一定是特殊字符串!!!
  20. //因为如果子串是特殊字符串那么,你在这个子串的基础上添加任何字符,也是特殊字符串。
  21. check = false;
  22. break;
  23. }
  24. }
  25. if (check) {
  26. ans = max(ans, static_cast<int>(strs[i].size()));
  27. }
  28. }
  29. return ans;
  30. }
  31. };

556. 下一个更大元素 III(整数转字符串)

将整数转化为字符串,然后从后往前寻找并且交换,保持交换之后的字符串的后面是最小排序。

  1. class Solution {
  2. public:
  3. int nextGreaterElement(int n) {
  4. string tmp = to_string(n);
  5. int i = tmp.size()-1;
  6. while(i > 0&& tmp[i] <= tmp[i-1]) i--;//从后往前找到第一个比后面值小的位置,也就是可以交换的位置i-1。
  7. if(i > 0) {
  8. int j = tmp.size()-1;
  9. while(j > 0&& tmp[j] <= tmp[i-1]) j--;//从后往前找到第一个比i-1位置的值大的位置,也就是用于交换的值。
  10. swap(tmp[j], tmp[i-1]);//交换两个位置的值
  11. reverse(tmp.begin() + i, tmp.end());//将交换位置i-1之后的值应该就是后面排列的最大值,将它们反转,取最小值。
  12. } else {
  13. return -1;
  14. }
  15. auto ans = stol(tmp);
  16. return ans > INT_MAX ? -1 : ans;
  17. }
  18. };

字符串匹配

KMP

参考连接:

https://www.zhihu.com/question/21923021/answer/281346746
https://leetcode-cn.com/problems/implement-strstr/solution/shua-chuan-lc-shuang-bai-po-su-jie-fa-km-tb86/

28. 实现 strStr()(KMP算法,多练习)

  1. class Solution {
  2. public:
  3. int strStr(string s, string p) {
  4. int n = s.size(), m = p.size();
  5. vector<int>next(m, -1);
  6. for(int i = 1, j = -1; i < m; i++) {
  7. while(j!=-1&&p[j+1]!= p[i]) j = next[j];
  8. if(p[i] == p[j+1]) j++;
  9. next[i] = j;
  10. }
  11. for(int j = -1, i = 0; i < n; i++) {
  12. while(j!=-1&&s[i]!=p[j+1]) j = next[j];
  13. if(s[i] == p[j+1]) j++;
  14. if(j == m-1) return i-m+1;
  15. }
  16. return -1;
  17. }
  18. };

字符串模拟

388. 文件的最长绝对路径(恶心至极)

哈希表+模拟

  1. class Solution {
  2. public:
  3. int lengthLongestPath(string input) {
  4. int n = input.size();
  5. unordered_map<int, string> mp;//哈系表存储前面的每一级目录,键为目录,值为目录具体字符串。
  6. bool have;
  7. string str;
  8. int ans = 0, i = 0;
  9. while(i < n) {
  10. int cnt = 0;
  11. str = "";
  12. while(i < n && input[i] == '\t') {//有多少个\t就代表有几级目录,也就是最终字符串有几个反斜杠
  13. ++cnt;
  14. ++i;
  15. }
  16. have = false;
  17. while(i < n && input[i] != '\n') {
  18. if(input[i] == '.') have = true;//只有文件名才有点,have为true的时候代表到了末尾。
  19. str += input[i];
  20. ++i;
  21. }
  22. ++i;//这里的++i跳过\n
  23. mp[cnt] = str;//存入哈系表
  24. if(have) {
  25. int sum = str.size();
  26. for(int i = 0; i < cnt; ++i) {//前面的每一级目录,
  27. sum += mp[i].size();
  28. }
  29. ans = max(ans, sum + cnt);//这里加上cnt是因为最终有多少个 \t就代表最终字符串有多少\。
  30. }
  31. }
  32. return ans;
  33. }
  34. };