- 字符串比较
- 165.比较版本号
 - 242. 有效的字母异位词(数组存储频率)、">242. 有效的字母异位词(数组存储频率)、
 - 205. 同构字符串(数组)">205. 同构字符串(数组)
 - 696. 计数二进制子串">696. 计数二进制子串
 - 3. 无重复字符的最长子串(哈希表+滑动窗口)">3. 无重复字符的最长子串(哈希表+滑动窗口)
 
 - 字符串理解
- 227. 基本计算器 II(经典)">227. 基本计算器 II(经典)
 - 409. 最长回文串(哈希表)">409. 最长回文串(哈希表)
 - 522. 最长特殊序列 II(脑筋急转弯)">522. 最长特殊序列 II(脑筋急转弯)
 - 556. 下一个更大元素 III(整数转字符串)">556. 下一个更大元素 III(整数转字符串)
 
 - 字符串匹配
 - KMP
- 参考连接:
 - 28. 实现 strStr()(KMP算法,多练习)">28. 实现 strStr()(KMP算法,多练习)
 
 - 字符串模拟
- 388. 文件的最长绝对路径(恶心至极)">388. 文件的最长绝对路径(恶心至极)
 
 
字符串比较
165.比较版本号
这一题说实话想得复杂了,将一段纯数字字符串转换为正确的数字类型,只需要采取进位相加的方式就行了。一段确定一个数字
class Solution {public:int compareVersion(string version1, string version2) {int n = version1.size(), m = version2.size();int i = 0, j = 0;while(i < n || j < m){int num1 = 0;for(; i < n &&version1[i] != '.'; i++){num1 = num1*10 + version1[i] - '0';}i++;int num2 = 0;for(; j < m&&version2[j] != '.'; j++){num2 = num2*10 + version2[j] - '0';}j++;if(num1 != num2){return num1 > num2 ? 1 : -1;}}return 0;}};
242. 有效的字母异位词(数组存储频率)、
class Solution {public:bool isAnagram(string s, string t) {if(s.size() != t.size())return false;vector<int> count(26);for(int i = 0; i < s.size(); i++){count[s[i] - 'a']++;count[t[i] - 'a']--;}for(int i = 0; i < 25; i++){if(count[i] != 0)return false;}return true;}};
205. 同构字符串(数组)
- 也是用数组解决的
 记录两个字符串每个位置的字符第一次出现的位置,如果两个字符串中相同位置的字符与它们第一次出现的位置一样,那么这两个字符串同构。
class Solution {public:bool isIsomorphic(string s, string t) {vector<int> first1(128,0),first2(128, 0);for(int i = 0; i < s.length(); i ++){if(first1[s[i]] != first2[t[i]])return false;first1[s[i]] = first2[t[i]] = i + 1;//能走到这一步就代表前面的等式也成立了。}return true;}};
696. 计数二进制子串
使用pre来记录前一个元素出现的次数,cur记录当前元素出现的次数
每次当pre大于或者等于前面元素出现的次数时,就记录下来
class Solution {public:int countBinarySubstrings(string s) {int pre = 0, cur = 1, count = 0;for(int i = 1; i < s.size(); i++){if(s[i] == s[i-1]){++cur;} else {pre = cur;cur = 1;}if(pre >= cur){++count;}}return count;}};
3. 无重复字符的最长子串(哈希表+滑动窗口)
简单哈希表,使用滑动窗口维护,哈希表的所有值都不能大于1
class Solution {public:int lengthOfLongestSubstring(string s) {int n = s.size(), ans = 0;if(n<2){return n;}unordered_map<char, int> hash;for(int i = 0, j = 0; i < n; i++){hash[s[i]]++;while(hash[s[i]]!=1&&j<i){hash[s[j]]--;j++;}ans = max(ans, i-j+1);}return ans;}};
字符串理解
227. 基本计算器 II(经典)
可以在字符串前面增加一个+号,然后将字符串分割成(运算符, 数字)形式,这样就可以从左往右处理了,
- 由于乘除的优先级高于加减,因此我们需要使用一个中间变量来存储高优先度的运算。
 - 这里还需要考虑到两个连在一起的数字
 
class Solution {public:int calculate(string s) {vector<int> stk;char preSign = '+';int num = 0;int n = s.length();for (int i = 0; i < n; ++i) {if (isdigit(s[i])) {//判断s[i]是不是数字num = num * 10 + int(s[i] - '0');//这里是计算多位数的情况}if (!isdigit(s[i]) && s[i] != ' ' || i == n - 1) {//如果是运算符,或者是最后一位,则计算num//千万注意,这里的运算符使用的是上一次的运算符switch (preSign) {case '+':stk.push_back(num);break;case '-':stk.push_back(-num);break;case '*':stk.back() *= num;//这里因为乘法有优先级break;default:stk.back() /= num;//出发也是一样。}preSign = s[i];//前一个符号num = 0;//当遇到一个符号之后前一个num置零}}return accumulate(stk.begin(), stk.end(), 0);}};//想法很好,如果是加号则直接入栈,减号则加负号入栈,乘除都是先计算后入栈、
409. 最长回文串(哈希表)
class Solution {public:int longestPalindrome(string s) {int n = s.size(), ans = 0;unordered_map<char, int> hash;for(auto it : s){hash[it]++;}for(auto it: hash){if(it.second%2==0){ans+=it.second;} else {ans+=it.second-1;}}return ans<n? ans+1:ans;}};
522. 最长特殊序列 II(脑筋急转弯)
class Solution {public:int findLUSlength(vector<string>& strs) {auto is_subseq = [](const string& s, const string& t) -> bool {int pt_s = 0, pt_t = 0;while (pt_s < s.size() && pt_t < t.size()) {if (s[pt_s] == t[pt_t]) {++pt_s;}++pt_t;}return pt_s == s.size();};int n = strs.size();int ans = -1;for (int i = 0; i < n; ++i) {bool check = true;for (int j = 0; j < n; ++j) {if (i != j && is_subseq(strs[i], strs[j])) {//如果当前字符串不是其他任意字符串的子串,则一定为特殊字符串。因为如果子串是特殊字符串,那么当前字符串也一定是特殊字符串!!!//因为如果子串是特殊字符串那么,你在这个子串的基础上添加任何字符,也是特殊字符串。check = false;break;}}if (check) {ans = max(ans, static_cast<int>(strs[i].size()));}}return ans;}};
556. 下一个更大元素 III(整数转字符串)
将整数转化为字符串,然后从后往前寻找并且交换,保持交换之后的字符串的后面是最小排序。
class Solution {public:int nextGreaterElement(int n) {string tmp = to_string(n);int i = tmp.size()-1;while(i > 0&& tmp[i] <= tmp[i-1]) i--;//从后往前找到第一个比后面值小的位置,也就是可以交换的位置i-1。if(i > 0) {int j = tmp.size()-1;while(j > 0&& tmp[j] <= tmp[i-1]) j--;//从后往前找到第一个比i-1位置的值大的位置,也就是用于交换的值。swap(tmp[j], tmp[i-1]);//交换两个位置的值reverse(tmp.begin() + i, tmp.end());//将交换位置i-1之后的值应该就是后面排列的最大值,将它们反转,取最小值。} else {return -1;}auto ans = stol(tmp);return ans > INT_MAX ? -1 : ans;}};
字符串匹配
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算法,多练习)
class Solution {public:int strStr(string s, string p) {int n = s.size(), m = p.size();vector<int>next(m, -1);for(int i = 1, j = -1; i < m; i++) {while(j!=-1&&p[j+1]!= p[i]) j = next[j];if(p[i] == p[j+1]) j++;next[i] = j;}for(int j = -1, i = 0; i < n; i++) {while(j!=-1&&s[i]!=p[j+1]) j = next[j];if(s[i] == p[j+1]) j++;if(j == m-1) return i-m+1;}return -1;}};
字符串模拟
388. 文件的最长绝对路径(恶心至极)
哈希表+模拟
class Solution {public:int lengthLongestPath(string input) {int n = input.size();unordered_map<int, string> mp;//哈系表存储前面的每一级目录,键为目录,值为目录具体字符串。bool have;string str;int ans = 0, i = 0;while(i < n) {int cnt = 0;str = "";while(i < n && input[i] == '\t') {//有多少个\t就代表有几级目录,也就是最终字符串有几个反斜杠++cnt;++i;}have = false;while(i < n && input[i] != '\n') {if(input[i] == '.') have = true;//只有文件名才有点,have为true的时候代表到了末尾。str += input[i];++i;}++i;//这里的++i跳过\nmp[cnt] = str;//存入哈系表if(have) {int sum = str.size();for(int i = 0; i < cnt; ++i) {//前面的每一级目录,sum += mp[i].size();}ans = max(ans, sum + cnt);//这里加上cnt是因为最终有多少个 \t就代表最终字符串有多少\。}}return ans;}};
