844.比较含退格的字符串
给定 s
和 t
两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true
。#
代表退格字符。
1.用栈来模拟整个退格删除过程,遇到字符就存入栈中,遇到退格符,就弹出栈的顶部元素
class Solution {
public:
bool backspaceCompare(string s, string t) {
string S; // 当栈来使用
string T; // 当栈来使用
for(int i = 0; i < s.size(); i++) {
if(s[i] != '#') S += s[i];
else if(!S.empty()) {
S.pop_back();
}
}
for(int i = 0; i < t.size(); i++) {
if(t[i] != '#') T += t[i];
else if(!T.empty()) {
T.pop_back();
}
}
if(S == T) return true;
return false;
}
};
2.从前向后双指针:从前向后遍历,如果遇到退格符,那么就向后跳一个元素进行比较,然后一次比较每一个位上的元素(我只能说很烦,真撕不出来吧)
class Solution {
public:
bool backspaceCompare(string s, string t) {
int SSkipNum = 0; // 记录s的数量
int TSkipNum = 0; // 记录t的数量
int i = s.size() - 1;
int j = t.size() - 1;
while(1) {
while(i >= 0) {
if(s[i] == '#') SSkipNum++;
else {
if(SSkipNum > 0) SSkipNum--;
else break;
}
i--;
}
while(j >= 0) {
if(t[j] == '#') TSkipNum++;
else {
if(TSkipNum > 0) TSkipNum--;
else break;
}
j--;
}
// 后半部分#消除完了,接下来比较s[i] != t[j]
if(i < 0 || j < 0) break; // 遍历到头了
if(s[i] != t[j]) return false;
i--;
j--;
}
// 说明s和t同时遍历完毕
if(i == -1 && j == -1) return true;
return false;
}
};
209.长度最小的子数组
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
1.暴力解法:两层for循环不断找到符合条件的子数组
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT32_MAX; // 最终的结果
int sum = 0; // 子序列的数值之和
int subLength = 0; // 子序列的长度
for(int i = 0; i < nums.size(); i++) {
sum = 0;
for(int j = i; j < nums.size(); j++) {
sum += nums[j];
if(sum >= target) {
subLength = j - i + 1;
result = result < subLength ? result : subLength;
break;
}
}
}
return result == INT32_MAX ? 0 : result;
}
};
2.滑动窗口法:第一层for循环遍历数组,接着细节在于用while不断调整子序列长度
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT32_MAX;
int sum = 0;
int i = 0;
int subLength = 0;
for(int j = 0; j < nums.size(); j++) {
sum += nums[j];
while(sum >= target) {
subLength = j - i + 1;
result = result < subLength ? result : subLength;
sum -= nums[i++];
}
}
return result == INT32_MAX ? 0 : result;
}
};
904.水果成篮
1.滑动窗口+哈希法:一个快指针一直遍历整个数组,直到发现第三种类型的水果,此时要将原本的第一种水果进行删除(慢指针右移),直到记录的只有两种水果。每一次遍历的最后都需要记录两个指针的差+1进行存储
class Solution {
public:
int totalFruit(vector<int>& fruits) {
unordered_map<int, int> map;
if(fruits.size() == 1) return 1;
int left = 0;
int right = 0;
int res = 0;
while(right < fruits.size()) {
map[fruits[right]]++;
while(map.size() > 2) {
map[fruits[left]]--;
if(map[fruits[left]] == 0) {
map.erase(fruits[left]);
}
left++;
}
res = max(res, right - left + 1);
right++;
}
return res;
}
};
76.最小覆盖子串
1.滑动窗口+哈希表(很难 我只能说)
class Solution {
public:
string minWindow(string s, string t) {
unordered_map<char, int> hs, ht;
//统计t中各个字符的个数
for(auto c : t) ht[c] ++;
string res;
int minLength = INT_MAX;
int cnt = 0;
for(int i = 0, j = 0; i < s.size(); i ++){
//i向右移动了一个有效字符
hs[s[i]] ++;
if(hs[s[i]] <= ht[s[i]]) cnt ++;
//如果有效字符的个数与t的长度一样,说明此时j ~ i 包含了t
if(cnt == t.size()){
//此时需要移动j,找到以i结尾的最小的包含t的串
//如果j对应的这个字符是一个冗余的字符,需要移动j
while(hs[s[j]] > ht[s[j]]){
hs[s[j]] --;
j ++;
}
if(i - j + 1 < minLength){
res = s.substr(j, i - j + 1);
minLength = res.size();
}
}
//继续查看下一个以i结尾包含t的长度最小的字串
}
return res;
}
};
感谢Carl,这集体还是没吃懂,我只能说,继续加油