Solution 1 : # Stack
class Solution {
public:
string build (string str){
stack<char> st;
for(auto c : str){
if(c == '#'){
if(!st.empty()){
st.pop();
}
else continue; // specail case when '#' is at the beginning etc
} // eg : '#f#g##', '####'
else st.push(c);
}
string result = "";
while(!st.empty()){
result += st.top();
st.pop();
}
return result;
}
bool backspaceCompare(string s, string t) {
string newS = build(s);
string newT = build(t);
return newS == newT;
}
};
Solution 2 : # Simulation
class Solution {
public:
int validLength(string& str){ // simulation
int k = 0; // k means the valid length of the string after remoing valid '#'
for(auto c : str){
if(c != '#'){
str[k++] = c;
}
else if(k > 0) k--; // valid '#' and erase one char
}
return k;
}
bool backspaceCompare(string s, string t) {
int L1 = validLength(s);
int L2 = validLength(t);
if(L1 != L2) return false;
for(int i = 0; i < L1; i++){ // special case like '###', '##'
if(s[i] != t[i]) return false;
}
return true;
}
};
Solution: # Sliding window
class Solution {
public:
string minWindow(string s, string t) {
int m = s.size(), n = t.size();
unordered_map<char, int> mp;
for(auto c : t) mp[c]++;
int ans = INT_MAX;
int start = 0;
int count = mp.size(); //需要匹配的种类数
int i = 0, j = 0;
while(j < m){
mp[s[j]]--;
if(mp[s[j]] == 0) count--; // 如果s字符串里面某字符匹配上了,就减小count的字符种类数
if(count == 0){
while(count == 0){
if(ans > j - i + 1){
ans = j - i + 1;
start = i;
}
mp[s[i]]++; //尝试移动左边界,因此撤回一个匹配的字符,mp对应字符+1
if(mp[s[i]] > 0) count++; // 这种情况下需要匹配新的种类的字符
i++; // 移动左边界
}
}
j++; // 移动右边界
}
return ans == INT_MAX ? "" : s.substr(start, ans);
}
Solution 1: #Two pointers, 建立收尾两个指针然后向中间移动就好了
class Solution {
public:
void reverseString(vector<char>& s) {
for(int i = 0, j = s.size() - 1; i < s.size() / 2; i++, j--){
swap(s[i], s[j]);
}
}
};
Solution 2: #Recursion
class Solution {
public:
void solve(vector<char>& s, int pos){
if(pos >= s.size() / 2) return;
swap(s[pos], s[s.size() - 1 - pos]);
solve(s, ++pos); // 这里不能用pos++,可以用++pos,或者pos+1
}
void reverseString(vector<char>& s) {
solve(s, 0);
}
};
Solution 1: #Simulation, 就是特殊判断边界情况就好
class Solution {
public:
string reverseStr(string s, int k) {
for(int i = 0; i < s.size(); i += 2 * k){
if(i + k > s.size()) reverse(s.begin() + i, s.end());
else reverse(s.begin() + i, s.begin() + i + k);
}
return s;
}
};
Solution 2: 手搓一个reverse库函数
class Solution {
public:
void s_reverse(string &s, int start, int end){
for(int i = start, j = end; i < j; i++, j--) swap(s[i], s[j]);
}
string reverseStr(string s, int k) {
for(int i = 0; i < s.size(); i += 2 * k){
if(i + k > s.size()) s_reverse(s, i, s.size() - 1); // attention !!!
else s_reverse(s, i, i + k - 1); // the index should minus 1
}
return s;
}
};
Solution 3: 用while循环♻️模拟
class Solution {
public:
string reverseStr(string s, int k) {
int pos = 0;
while(pos < s.size()){
if(pos + k > s.size()) reverse(s.begin() + pos, s.end());
else reverse(s.begin() + pos, s.begin() + pos + k);
pos += 2 * k;
}
return s;
}
};
Solution: #Two Pointers, 要从后往前填充
#include<bits/stdc++.h>
using namespace std;
int main(){
string s;
while(cin >> s){
int old = s.size() - 1;
int count = 0;
for(int i = 0; i < s.size(); i++){
if(s[i] >= '0' && s[i] <= '9') count++;
}
s.resize(s.size() + count * 5);
int NewIndex = s.size() - 1;
while(old >= 0){
if(s[old] >= '0' && s[old] <= '9'){
s[NewIndex--] = 'r';
s[NewIndex--] = 'e';
s[NewIndex--] = 'b';
s[NewIndex--] = 'm';
s[NewIndex--] = 'u';
s[NewIndex--] = 'n';
}
else{
s[NewIndex--] = s[old];
}
old--;
}
cout << s << endl;
}
return 0;
}
151. Reverse Words in a String
Solution 1: #Two Pointers
class Solution {
public:
string reverseWords(string s) {
int slow = 0, fast = 0;
bool wordStart = false;
reverse(s.begin(), s.end());
for(fast; fast < s.size(); fast++){
if(s[fast] != ' '){
if(wordStart && slow != 0) s[slow++] = ' '; // add blankspace
int start = fast;
while(fast < s.size() && s[fast] != ' '){
s[slow++] = s[fast++];
}
reverse(s.begin() + slow - (fast - start), s.begin() + slow);
wordStart = true; // new word starts
}
}
s.resize(slow); // resize the string
return s;
}
};
Solution 2: #Stack,用栈来模拟整个过程,简单易懂
class Solution {
public:
string reverseWords(string s) {
string result = "";
stack<string> st;
for(int i = 0; i < s.size(); i++){
if(s[i] == ' ') continue;
string word = "";
while(s[i] != ' ' && i < s.size()) word += s[i++];
st.push(word);
}
while(!st.empty()){
result += st.top();
st.pop();
if(!st.empty()) result += " "; //不是最后一个单词的情况就要加空格
}
return result;
}
};
55. 右旋字符串(第八期模拟笔试)
Solution 1: 不断翻转就行,因为不能开辟额外空间
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
string s;
cin >> n;
cin >> s;
reverse(s.begin(), s.end());
reverse(s.begin(), s.begin() + n);
reverse(s.begin() + n, s.end());
cout << s << endl;
return 0;
}
Solution 2: 如果可以开辟额外空间的话,做法就是开子串
#include<bits/stdc++.h>
using namespace std;
int main(){
int k; cin >> k;
string s; cin >> s;
string ss = s.substr(s.size() - k, k);
s.erase(s.size() - k, k);
ss += s;
cout << ss << endl;
return 0;
}
28. Find the Index of the First Occurrence in a String
Solution 1: 直接使用STL库函数
class Solution {
public:
int strStr(string haystack, string needle) {
size_t found = haystack.find(needle);
if(found == string::npos) return -1;
else return found;
}
};
Solution 2: 直接手动模拟
class Solution {
public:
int strStr(string haystack, string needle) {
int left = 0, right = needle.size() - 1;
while(right < haystack.size()){
if(haystack[left] == needle[0] && haystack[right] == needle[needle.size() - 1]){
int i = left, j = 0;
while(i <= right && haystack[i++] == needle[j++]){
if(i == right + 1) return left;
}
}
left++;
right++;
}
return -1;
}
};
Solution 3: # KMP, 不知道这里用KMP是不是自作多情了……但是也顺带复习一下吧
KMP最重要的是前缀表(prefix table),前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配。前缀表就是求最长相同前后缀的长度。KMP最重要的就是构建next数组。修考重点!!!!!经常回顾!
class Solution {
private:
vector<int> next(string needle){ // 计算next数组
int n = needle.size();
vector<int> lps(n, 0); //初始化公共前缀都为0
for(int i = 1, len = 0; i < n;){
if(needle[i] == needle[len]){
lps[i++] = ++len; // 当前字符匹配
}
else if(len){
len = lps[len - 1]; // 如果不匹配且最长公共前后缀长度不为 0,回溯到前一个最长公共前后缀的位置
}
else{
lps[i++] = 0; // 如果不匹配且最长公共前后缀长度为 0,说明当前字符无法匹配任何前后缀
}
}
return lps;
}
public:
int strStr(string haystack, string needle) {
int m = haystack.size(), n = needle.size();
if(!n) return 0; //// 如果 needle 为空字符串,直接返回 0
vector<int> lps = next(needle);
for(int i = 0, j = 0; i < m;){
if(haystack[i] == needle[j]) i++, j++; // // 如果当前字符匹配成功
if(j == n) return i - j; // // 如果 j 达到了 needle 的长度,说明完全匹配,返回起始位置
if(i < m && haystack[i] != needle[j]){
//// 如果当前字符不匹配,根据最长公共前后缀数组 lps 跳过部分已匹配的内容
j ? j = lps[j - 1] : i++; // // 如果 j 不为 0,根据 lps 调整 j;否则,i 后移一位
}
}
return -1;
}
};
459. Repeated Substring Pattern
Solution 1: 把两倍的字符串拼接在一起然后掐头去尾再找是否有原字符串
class Solution {
public:
bool repeatedSubstringPattern(string s) {
string t = s + s;
t.erase(t.begin());
t.erase(t.end() - 1);
if(t.find(s) == string::npos) return false;
return true;
}
};
Solution 2: # Brute force, 暴力找出重复子串
class Solution {
public:
bool repeatedSubstringPattern(string s) {
string str = "";
int pos = 0;
while(pos < s.size() / 2){
str += s[pos];
string tmp = str;
while(tmp.size() < s.size()) tmp += str;
if(tmp == s) return true;
pos++;
}
return false;
}
};
class Solution {
public:
int longestPalindrome(string s) {
unordered_map<char, int> mp;
for(char c : s) mp[c]++;
int count = 0;
bool hasOdd = false;
for(auto &itr : mp){
if(itr.second % 2 == 0){
count += itr.second;
}
else{
count += itr.second - 1;
hasOdd = true;
}
}
if(hasOdd) count += 1;
return count;
}
};