LeetCode系列之字符串专题
1. 字符串题目概述
https://leetcode-cn.com/tag/string/
字符串的操作可以归结为以下几类:
- 字符串的比较、连接操作
- 涉及子串的操作,比如前缀、后缀等
- 字符串间的匹配操作,如KMP算法、BM算法等
2. 典型题目
2.1 翻转字符串里的单词
https://leetcode-cn.com/problems/reverse-words-in-a-string/
string reverseWords(string s) { trimStr(s); reverse(s.begin(), s.end()); reverseEachWord(s); return s; } void trimStr(string& s) { if (s.empty()) return; bool gotFirstAlphabet = false; int current = 0, nspaces = 0; for (int i = 0; i < s.length(); i++) { if (s[i] == ' ') { if (!gotFirstAlphabet) continue; nspaces++; if (nspaces > 1) continue; s[current++] = s[i]; } else { gotFirstAlphabet = true; nspaces = 0; s[current++] = s[i]; } } if (current > 0 && s[current - 1] == ' ') current--; s.resize(current); } void reverseEachWord(string& s) { if (s.empty()) return; int start = -1, end = -1; for (int i = 0; i < s.length(); i++) { if (s[i] != ' ') { if (start < 0) start = i; } else { end = i; reverse(s.begin() + start, s.begin() + end); start = -1; end = -1; } } reverse(s.begin() + start, s.end()); }
官方解答如下:
string reverseWords(string s) { // 反转整个字符串 reverse(s.begin(), s.end()); int n = s.size(); int idx = 0; for (int start = 0; start < n; ++start) { if (s[start] != ' ') { // 填一个空白字符然后将idx移动到下一个单词的开头位置 if (idx != 0) s[idx++] = ' '; // 循环遍历至单词的末尾 int end = start; while (end < n && s[end] != ' ') s[idx++] = s[end++]; // 反转整个单词 reverse(s.begin() + idx - (end - start), s.begin() + idx); // 更新start,去找下一个单词 start = end; } } s.erase(s.begin() + idx, s.end()); return s; }
显得简洁不少!注意领会学习。
时间复杂度O(N),空间复杂度O(1)。
2.2 最后一个单词的长度
https://leetcode-cn.com/problems/length-of-last-word/
int lengthOfLastWord(string s) { reverse(s.begin(), s.end()); int start = findFirstLetter(s); int length = 0; for (int i = start; i < s.size(); i++) { if (s[i] == ' ') { return length; } else { length++; } } return length; } int findFirstLetter(string& s) { int index = 0; for (int i = 0; i < s.size(); i++) { if (s[i] != ' ') { index = i; break; } } return index; }
想写得清晰易懂一些,所以把找第一个非空字符单独拆成一个函数。
时间复杂度O(N),空间复杂度O(1)。
2.3 括号生成
https://leetcode-cn.com/problems/generate-parentheses/
2.4 外观数列
https://leetcode-cn.com/problems/count-and-say/
2.5 实现strStr()
https://leetcode-cn.com/problems/implement-strstr/
2.6 最长回文子串
https://leetcode-cn.com/problems/longest-palindromic-substring/
2.7 检测大写字母
https://leetcode-cn.com/problems/detect-capital/
bool detectCapitalUse(string word) { std::regex reg("^[A-Z]+$|^[a-z]+$|^[A-Z][a-z]+$"); return std::regex_match(word, reg); }
手写检测可以通过,且性能较高。这里又尝试了一下正则表达式的解法,也不错。
正则表达式的时间复杂度是O(N),空间复杂度O(1)。
2.8 最长有效括号
https://leetcode-cn.com/problems/longest-valid-parentheses/
2.9 二进制求和
https://leetcode-cn.com/problems/add-binary/
2.10 反转字符串
https://leetcode-cn.com/problems/reverse-string/
void reverseString(vector<char>& s) { int head = 0; int tail = s.size() - 1; while (head < tail) { swap(s[head], s[tail]); head++; tail--; } }
tail = s.size() - 1; 是为了让出末尾的 ‘\0’。
时间复杂度O(N),空间复杂度O(1)。