二刷刷到滑动窗口,发现有一些细节和遗漏,在此补充

实际上关于滑动窗口的题还有一题:最小长度的子数组

进入正题

水果成篮

LeetCode904水果成篮

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。

你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:

你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。

你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。

一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。

给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。

示例 1:

输入:fruits = [1,2,1]

输出:3

解释:可以采摘全部 3 棵树。

示例 2:

输入:fruits = [0,1,2,2]

输出:3

解释:可以采摘 [1,2,2] 这三棵树。

如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。

示例 3:

输入:fruits = [1,2,3,2,2]

输出:4

解释:可以采摘 [2,3,2,2] 这四棵树。

如果从第一棵树开始采摘,则只能采摘 [1,2] 这两棵树。

思路

题目的要求,换个说法就是:找到一段数组中的元素,该段元素中类型最多为2种,如果段中元素达到3种就直接停止。我们的目标是使这个段中元素的个数尽可能多

例如:(示例3)

[[1,2],3,2,2]
[[1,2,3],2,2]

如果是从1开始取的话,到3就会停止,最终只能取到[1, 2],显然这不是题设规则下的最优解

如果我们从2开始取呢?

[1,[2,3],2,2]
[1,[2,3,2],2]
[1,[2,3,2,2]]

最后结果是[2,3,2,2],这是最优解

这里的“段”,实际上很类似窗口,由此可以联想到滑动窗口算法

我们需要维护的窗口内只能存在两种类型的数,一旦出现第三种,缩小窗口的左边界,直到再次满足条件后,继续使右边界扩大

思路很明确了,那怎么实现呢?关键点是如何记录元素出现次数

根据之前的经验,要记录某种东西出现的次数,可以考虑用哈希表

这里创建一个哈希表unordered_map,键是当前的遍历值,值是出现次数

判断哈希表的大小,一旦大于2,就触发循环,在map中找到以左指针指向的数组值为哈希表键的元素,将其移除即可(注意,要先删除干净其键对应的值,这里在下面细说),同时,left的指针向右移动。

最后,左右指针作差,更新结果保存变量(取最大的保存)

代码

坑(关于map的使用)

思路定下来了,写代码吧

这是根据思路写的第一版

class Solution {
public:
int totalFruit(vector<int>& fruits) {
//定义左指针
int left = 0;
int res = 0;
unordered_map<int, int> typeCount;//定义一个哈希表,键是遍历值
for(int right = 0; right < fruits.size(); ++right){
typeCount[fruits[right]]++;
while(typeCount.size() > 2){//如果类型大于2,开始移动左指针缩小窗口
auto it = typeCount.find(fruits[left]);
if(it != typeCount.end()){//找到左指针对应的键值,删除
typeCount.erase(it);
}
left++;
}
res = max(res, right - left + 1);
}
return res;
}
};

看起来没有什么问题,其实问题挺大的,并且很隐蔽

问题主要出现在以下部分:

				auto it = typeCount.find(fruits[left]);
if(it != typeCount.end()){//找到左指针对应的键值,删除
typeCount.erase(it);
}

这里的本意是:在map中找到以fruits[left]为键的元素,然后将其移除。

这是符合我们之前的逻辑推导的,但是在代码落实的时候出问题了

在map中查找某个键对应的值,返回的是一个迭代体,我们可以通过it != typeCount.end()判断是否查找到对应的键值

这里在找到键值对后,我直接把返回的迭代体删了

只删迭代体对象没用啊,map中对应的键值对是不受影响的,也就是说,删了个寂寞

正确删除map中键值对的操作是:

  • 使用find找到键值对
  • 将键对应的值(it->second)全部删除
  • 判断当前键对应的值为0后,删除指向键值对的迭代体
完整代码

根据上述讨论修改后的代码如下:

class Solution {
public:
int totalFruit(vector<int>& fruits) {
int left = 0;//定义左指针
int res = 0;
unordered_map<int, int> typeCount;//定义一个哈希表,键是遍历值
for(int right = 0; right < fruits.size(); ++right){
typeCount[fruits[right]]++;//记录出现次数
while(typeCount.size() > 2){//如果类型大于2,开始移动左指针缩小窗口
auto it = typeCount.find(fruits[left]);//使用find找到键值对,并返回迭代体对象
it->second--;//将键对应的值全部删除
if(it->second == 0){
typeCount.erase(it); //删除指向键值对的迭代体
}
left++;//左指针右移
}
res = max(res, right - left + 1);//将最大值更新到结果变量
}
return res;
}
};

本题思路其实不难想,主要问题出现在代码实现,对于map的使用不熟练

最小覆盖子串

LeetCode76最小覆盖子串

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。

注意:

对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。

如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例 1:

输入:s = "ADOBECODEBANC", t = "ABC"

输出:"BANC"

解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。

示例 2:

输入:s = "a", t = "a"

输出:"a"

解释:整个字符串 s 是最小覆盖子串。

示例 3:

输入: s = "a", t = "aa"

输出: ""

解释: t 中两个字符 'a' 均应包含在 s 的子串中,

因此没有符合条件的子字符串,返回空字符串。

思路

大体思路

从题目给的模板(minWindow)可以得到提示,这题可以用滑动窗口算法解(其实不看也应该能想到)

我们需要维护一个窗口

窗口的右边界不断遍历输入字符串s,往窗口内添加字符,直到当前窗口内出现目标字符串t中的所有字符,此时移动左边界来缩小窗口,取出冗余字符

好了,此题关于滑动窗口部分的思路讨论完毕

很清晰是吧?然后写代码的时候会发现根本写不出

因为很多思路中理所当然的地方用代码很难实现

代码实现思路

那么用代码写的时候应该怎么考虑呢?

我们要维护两个哈希表(unordered_map),hsht

ht用于统计目标字符串t中各字符出现的次数;

hs用于记录当前遍历字符出现的次数;(至于为什么是“次数”,后面会说)

定义结果字符串res、左指针变量left、计数变量count

右指针遍历输入字符串s,将遍历字符加入hs

如果当前遍历字符是目标字符串t中的目标字符,且出现次数小于等于ht中的出现次数,计数变量加1

代码实现中,记录当前遍历字符出现的次数是为了判断是否包含字符串t中所有的字符。

具体来说,算法维护两个哈希表:ht和hs,分别表示字符串t和当前窗口内的字符串s中每个字符的出现次数。

当扫描到一个新的字符时,程序会检查该字符是否在ht中出现。如果出现,就将hs中对应的计数器加1,并判断是否小于等于ht中的计数器。如果小于等于,说明该字符是目标字符之一,并且当前窗口内仍然存在未满足条件的目标字符,因此 count 计数器加1。

通过统计s中目标字符出现的次数,可以判断当前窗口内是否包含t中的所有字符。当count计数与t长度相等时表示当前窗口中已经包含有全部t中的目标字符,需要更新结果字符串res。

因此,记录遍历字符出现的次数在这个算法中起到至关重要的作用,它帮助我们确定了窗口内目标字符的数量,从而实现了正确的滑动窗口匹配。

首先,需要定义一堆变量

class Solution {//输入:s = "ADOBECODEBANC", t = "ABC"
public:
string minWindow(string s, string t) {
unordered_map<char, int>hash4s, hash4t;//用于统计s和t的hash表,键为对应字符,值为出现次数
int left = 0;
string res;//定义结果字符串
int count = 0;//用于统计s中目标字符(t中字符)出现的次数
...
}

然后我们遍历字符串t,将其中的字符出现次数统计到hash4t中

class Solution {
public:
string minWindow(string s, string t) {
...
for(int i = 0; i < t.size(); ++i){//统计t的字符出现次数
hash4t[t[i]]++;
}
}

接下来开始遍历字符串s,将遍历到的元素统计到hash4s中,然后我们去hash4t中找当前hash4s中被记录的元素是否出现过

目的是为了看当前元素是不是目标元素,如果是目标元素,并且该元素在s中出现的次数少于t中出现的次数时,那么我们认为找到了一个有效的目标字符

class Solution {
public:
string minWindow(string s, string t) {
...
for(int i = 0; i < t.size(); ++i){//统计t的字符出现次数
hash4t[t[i]]++;
}
for(int right = 0; right < s.size(); ++right){//遍历字符串s,对应字符出现后在hash4s记录
hash4s[s[right]]++;
if(hash4s[s[right]] <= hash4t[s[right]]){
count++;//计数+1
}
}
}

这里需要特别解释一下(关于代码实现)

1、实际上hash4t在一开始的时候大小为3,为什么还能一直与大于3位置的元素进行比较

举个例子,我们一开始统计完t的元素后,hash4t={'A': 1, 'B': 1, 'C': 1}。

然后我们开始遍历s,第一次得到A,A在s中出现一次,在t中也出现一次,这是一个有效的目标字符,因此计数加1

第二次遍历s得到D,而D在t中是没有的,在hash4t中也没有,D不是目标字符,但因为进行了比较,所以hash4t中也要生成一个关于D的记录,此时hash4t={'A': 1, 'B': 1, 'C': 1, 'D': 0}

结论就是:哈希表会给不存在的键值一个默认值

继续

在遍历s的过程中,if条件不断被触发,当我们的窗口内收集到了3个目标字符(ADOBEC),此时count = 3

因为已经收集到3个有效的目标字符,所以我们要对当前子串进行保存

class Solution {
public:
string minWindow(string s, string t) {
...
for(int i = 0; i < t.size(); ++i){//统计t的字符出现次数
hash4t[t[i]]++;
}
for(int right = 0; right < s.size(); ++right){//遍历字符串s,对应字符出现后在hash4s记录
hash4s[s[right]]++;
if(hash4s[s[right]] <= hash4t[s[right]]){
count++;//计数+1
}
while(hash4s[s[left]] > hash4t[s[left]]){//此时,要移动左边界去除当前窗口中的冗余字符
//注意,是先减值,再移动left!!!!
hash4s[s[left]]--;//对应减少hs中的值,直到hs中的目标字符出现次数均与ht中相等
left++;//移动左边界
}
if(count == t.size()){//找到3个有效目标字符
if(res.empty() || right - left + 1 < res.size()){
res = s.substr(left, right - left + 1);//截取当前窗口内字符串作为结果字符串
}
}
}
}

关键点!!!!!!!!

按理来说应该开始缩小窗口的左边界,但是如果现在马上缩的话,当前子串中目标字符的数量就会又不满足3个了,我们可能会因此漏掉某些情况或者需要进行多余的处理

比如如果变量到ADOBEC立刻缩小左边界,那么此时窗口内为DOBEC,没凑齐目标字符,因此右边界继续移动

当移动到DOBECODEB时,B出现了2次,此时仍然没有凑齐目标字符

再往后移动到了DOBECODEBA,终于又凑齐3个目标字符,但是该子串长于第一次找到的子串因此不更新,此时缩小左边界

缩到CODEBA,继续缩ODEBA,不满足了,右边界继续移动直到ODEBANC又再次满足

然后是缩小左边界,缩到ANC不满足条件,但是因为s已经遍历完成,因此我们需要回退到上一个满足条件的位置即BANC,期间我们要需要比较其是否为目前找到的最小子串,最后返回结果

根据上面的分析,如果我们立刻进行缩窗操作,最后也是可以得到结果的,但是需要进行更多的逻辑控制

因此我们选择先不缩小窗口,继续遍历

那么还是跟前面一样,遇到目标字符,并且目标字符在s中出现的次数小于t中的次数(有效目标字符),count就加1

否则就在hash4t中创建一个默认值,这样做你会发现当遍历到ADOBECODEB时,B已经出现了两次而我们还没有对其进行处理

先别急,继续遍历到ADOBECODEBA,OK此时我们要进行缩窗操作

class Solution {
public:
string minWindow(string s, string t) {
...
for(int i = 0; i < t.size(); ++i){//统计t的字符出现次数
hash4t[t[i]]++;
}
for(int right = 0; right < s.size(); ++right){//遍历字符串s,对应字符出现后在hash4s记录
hash4s[s[right]]++;
if(hash4s[s[right]] <= hash4t[s[right]]){
count++;//计数+1
}
while(hash4s[s[left]] > hash4t[s[left]]){//此时,要移动左边界去除当前窗口中的冗余字符
//注意,是先减值,再移动left!!!!
hash4s[s[left]]--;//对应减少hs中的值,直到hs中的目标字符出现次数均与ht中相等
left++;//移动左边界
}
}
}

注意我们缩小左边界时的逻辑,下面以实例来说明

遍历到ADOBECODEBA时,此时

hash4t={'A': 1, 'B': 1, 'C': 1,'D': 0, 'O': 0, 'E': 0}

hash4s={'A': 2, 'B': 2, 'C': 1,'D': 1, 'O': 2, 'E': 2}

那么此时hash4s[s[left]] > hash4t[s[left]]这个条件会一直满足,因此s[left]在hash4s中的值会对应的被减少

同时left指针也不断往右移动,缩小窗口,最终left来到第二个B的位置,此时while循环的条件无法满足,跳出循环

ADOBECODEBANC

left

此时hash4s={'A': 1, 'B': 1, 'C': 0,'D': 0, 'O': 0, 'E': 0}

当前子串由于缺少C还不满足条件,且s还没有遍历完,因此right指针继续向右遍历s

当s遍历完成,C正好也获取到了,并且此时的子串也是长度最小的一个,返回结果即可

还要注意的一点是关于count的

其实我们可能会有一个惯性,认为只要count=3就必须更新子串,其实不是,虽然每次我们都触发count=3的if条件,但是如果当前子串的长度没有之前的小,也是不会更新最小子串的

也就是说,肯会有很多个满足条件的子串,但我们只保存最小的

完整代码

class Solution {
public:
string minWindow(string s, string t) {
unordered_map<char, int> hash4t, hash4s;
int left = 0;
int count = 0;
string res;
for(int i = 0; i < t.size(); ++i){//统计t的字符出现次数
hash4t[t[i]]++;
}
//遍历字符串s
for(int right = 0; right < s.size(); ++right){
hash4s[s[right]]++;//标记出现过的元素
if(hash4s[s[right]] <= hash4t[s[right]]){//如果当前字符为有效目标字符,计数加1
count++;
}
//处理窗口左边界
while(hash4s[s[left]] > hash4t[s[left]]){
hash4s[s[left]]--;//对应计数值减减
left++;//窗口左边界右移
}
//处理收集到3个有效目标字符时的情况
if(count == t.size()){
if(res.empty() || right - left + 1 < res.size()){//保存最小的子串
res = s.substr(left, right - left + 1);
}
}
}
return res;
}
};

再提供一个Python版的方便忘了的时候自己debug想想

from collections import defaultdict

def minWindow(s, t):
hash4s = defaultdict(int)
hash4t = defaultdict(int)
left = 0
res = ""
count = 0 for char in t:
hash4t[char] += 1 for right in range(len(s)):
hash4s[s[right]] += 1 if hash4s[s[right]] <= hash4t[s[right]]:
count += 1 while hash4s[s[left]] > hash4t[s[left]]:
hash4s[s[left]] -= 1
left += 1 if count == len(t):
if res == "" or right - left + 1 < len(res):
res = s[left:right + 1] return res

字符串的排列

https://leetcode.cn/problems/permutation-in-string/

给你两个字符串 s1s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false

换句话说,s1 的排列之一是 s2子串

示例 1:

输入:s1 = "ab" s2 = "eidbaooo"
输出:true
解释:s2 包含 s1 的排列之一 ("ba").

示例 2:

输入:s1= "ab" s2 = "eidboaoo"
输出:false

提示:

  • 1 <= s1.length, s2.length <= 104
  • s1s2 仅包含小写字母

思路

本题为最小覆盖子串的青春版,主要思想是利用了滑动窗口+哈希表统计出现次数

首先,创建两个数组充当哈希表

class Solution {
public:
bool checkInclusion(string s1, string s2) {
if(s1.size() > s2.size()) return false;
vector<int> hash_s1(26, 0);//创建两个数组用于记录字符串出现的次数
vector<int> hash_s2(26, 0);
int winLen = s1.size();//获取窗口大小
}
};

注意!!!还要将最小的字符串(也就是s1)的长度作为窗口大小保存

然后我们遍历两个字符串的前winLen个元素,即初始时窗口内的元素

class Solution {
public:
bool checkInclusion(string s1, string s2) {
...
for(int i = 0; i < winLen; ++i){
hash_s1[s1[i] - 'a']++;
hash_s2[s2[i] - 'a']++;
}
if(hash_s1 == hash_s2) return true;
}
};

以s1 = "ab" s2 = "eidbaooo"为例,那么此时有

hash_s1 = {0:1, 1:1}
hash_s2 = {5:1, 9:1}

这俩玩意显然不相等,要不然就触发返回条件了

接下来去遍历s2,注意遍历的起始点是winLen而不是0,并且遍历过程中我们需要不断移动窗口

class Solution {
public:
bool checkInclusion(string s1, string s2) {
...
for(int right = winLen; right < s2.size(); ++right){
hash_s2[s2[right - winLen] - 'a']--;
hash_s2[s2[right] - 'a']++;
if(hash_s1 == hash_s2) return true;
}
return hash_s1 == hash_s2;
}
};

移动窗口的过程中,不断判断两个哈希表是否满足条件,满足就返回

遍历结束再次判断,返回判断结果

代码

class Solution {
public:
bool checkInclusion(string s1, string s2) {
if(s1.size() > s2.size()) return false;
vector<int> hash_s1(26, 0);//创建两个数组用于记录字符串出现的次数
vector<int> hash_s2(26, 0);
int winLen = s1.size();//获取窗口大小 for(int i = 0; i < winLen; ++i){//遍历两字符串的前winLen个值,也就是第一个窗口中的值
hash_s1[s1[i] - 'a']++;
hash_s2[s2[i] - 'a']++;
}//如果此时两个哈希表直接相等了,那么说明在第一个窗口就已经确定s2包含s1的排列之一,返回结果即可
if(hash_s1 == hash_s2) return true; //开始从第二个窗口遍历s2
for(int right = winLen; right < s2.size(); ++right){
hash_s2[s2[right - winLen] - 'a']--;//窗口的左边界向右移动
hash_s2[s2[right] - 'a']++;//窗口的右边界向左移动
//窗口滑动完成,比较此时两哈希表是否相等
if(hash_s1 == hash_s2) return true;
//不相等就继续滑动
}//遍历完s2最后再判断一次两表是否相等,返回结果
return hash_s1 == hash_s2;
}
};

从本题可以直观体会到,双指针与滑动窗口的一个区别

滑动窗口的精髓在于"缩小窗口"这一操作,不同的场景会有不同的缩小时机

本题中,窗口是固定的,因此右边界移动时左边界也必须跟着移动来保证窗口大小固定

找到字符串中所有字母异位词

https://leetcode.cn/problems/find-all-anagrams-in-a-string/description/

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。

示例 1:

输入: s = "cbaebabacd", p = "abc"

输出: [0,6]

解释:

起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。

起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。

示例 2:

输入: s = "abab", p = "ab"

输出: [0,1,2]

解释:

起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。

起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。

起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。

提示:

1 <= s.length, p.length <= 3 * 104

s 和 p 仅包含小写字母

代码

class Solution {
public:
//滑动窗口
vector<int> findAnagrams(string s, string p) {
if(s.size() < p.size()) return vector<int>();
vector<int> hash_s(26, 0);
vector<int> hash_p(26, 0);
int winLen = p.size();
vector<int> res; //遍历两个字符串的初始窗口内的元素
for(int i = 0 ; i < winLen; ++i){
hash_s[s[i] - 'a']++;
hash_p[p[i] - 'a']++;
}
//此时如果俩hash相等,那么就获得一个结果,保存其位置(位置就是0处)
if(hash_s == hash_p) res.push_back(0); //然后从第二个窗口开始遍历
for(int right = winLen; right < s.size(); ++right){
hash_s[s[right - winLen] - 'a']--;//左边界缩窗
hash_s[s[right] - 'a']++;//右边界移动
if(hash_s == hash_p) res.push_back(right - winLen + 1);
}
return res;
}
};

【LeetCode滑动窗口专题】水果成篮 + 最小覆盖子串(hard)+ 字符串的排列的更多相关文章

  1. LeetCode 滑动窗口题型整理

    一.滑动窗口题型模板 /* * 滑动窗口类型: 模板 */ public List<Integer> slideWindowMode(String s, String t) { // 1 ...

  2. 【Leetcode 滑动窗口】顺次数(1291)

    题目 我们定义「顺次数」为:每一位上的数字都比前一位上的数字大 1 的整数. 请你返回由 [low, high] 范围内所有顺次数组成的 有序 列表(从小到大排序).   示例 1: 输出:low = ...

  3. LeetCode - 滑动窗口最大值

    给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口内的 k 个数字.滑动窗口每次只向右移动一位. 返回滑动窗口中的最大值. 输入: nums ...

  4. [Swift]LeetCode904. 水果成篮 | Fruit Into Baskets

    In a row of trees, the i-th tree produces fruit with type tree[i]. You start at any tree of your cho ...

  5. 7、滑动窗口套路算法框架——Go语言版

    前情提示:Go语言学习者.本文参考https://labuladong.gitee.io/algo,代码自己参考抒写,若有不妥之处,感谢指正 关于golang算法文章,为了便于下载和整理,都已开源放在 ...

  6. Leetcode(三)无重复字符的最长子串

    3. 无重复字符的最长子串 题目描述 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最 ...

  7. [LeetCode] 76. 最小覆盖子串 ☆☆☆☆☆(滑动窗口)

    https://leetcode-cn.com/problems/minimum-window-substring/solution/hua-dong-chuang-kou-suan-fa-tong- ...

  8. [LeetCode]438. 找到字符串中所有字母异位词、76. 最小覆盖子串(滑动窗口解决子串问题系列)

    题目438. 找到字符串中所有字母异位词 给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引. 说明: 字母异位词指字母相同,但排列不同的字符 ...

  9. leetcode全部滑动窗口题目总结C++写法(完结)

    3. 无重复字符的最长子串 A: 要找最长的无重复子串,所以用一个map保存出现过的字符,并且维持一个窗口,用le和ri指针标识.ri为当前要遍历的字符,如果ri字符在map中出现过,那么将le字符从 ...

  10. 滑动窗口通用解leetcode字符串匹配问题

    滑动窗口,这玩意解决一些字符串匹配的题目是真的挺好用的,虽然本质还是双指针. 思路: 1.维护一个窗口,不断的向右边移动 2.满足要求后,移动左边,当不满足时,跳出. 3.重复1,2.得出答案. 下面 ...

随机推荐

  1. 【转帖】淫技巧 | 如何查看已连接的wifi密码

    主题使用方法:https://github.com/xitu/juejin-markdown-themes theme: juejin highlight: github 一.引言 在实际工作中,常常 ...

  2. [转帖]Tail Latency学习

    https://www.cnblogs.com/Rohn/p/15123758.html Latency,中文译作延迟,Tail Latency即尾延迟. 实际生产中的Latency是一种(概率)分布 ...

  3. Redis 的简单学习与整理

    Redis 的简单学习与整理 背景 最近一直进行Redis性能调优和高可用的课题 但是不管什么课题,第一步应该是学习与使用redis 之前总结过 rdb 与 rdr 分析 键值对等内容. 但是发现想要 ...

  4. MySQL新增数据,修改数据,删除数据

    连接本地mysql语句 mysql -hlocalhost -uroot -proot DML-介绍 DML英文全称是:用来对数据库中表的数据记录进行 增 删 改 操作. 增加使用 insert 删除 ...

  5. bootstrap ----- bootstrap table表格参数

    表格参数: 名称 标签 类型 默认 描述 - data-toggle String 'table' 不用写 JavaScript 直接启用表格. classes data-classes String ...

  6. easyui 使用不同的url以获取不同数据源信息

    转载 https://www.bbsmax.com/A/kjdw1x06JN/ https://blog.csdn.net/lixinhui199/article/details/50724081 参 ...

  7. 【云原生】为什么要虚拟化,为什么要容器,为什么要Docker,为什么要K8S?

    前言 如标题中的问题所提到的虚拟化,容器,Docker和K8s那样,我们不妨这样问:这些技术到底适用于哪些场景,有没有别的技术可以替代?这些技术的优劣在哪里? 下面我将针对性地从以上几个问题的出发点, ...

  8. Python自动化办公--Pandas玩转Excel数据分析【二】

    相关文章: Python自动化办公--Pandas玩转Excel[一] Python自动化办公--Pandas玩转Excel数据分析[三] python处理Excel实现自动化办公教学(含实战)[一] ...

  9. Hadoop3 No FileSystem for scheme "hdfs"

    Hadoop3 No FileSystem for scheme "hdfs" 异常信息: org.apache.hadoop.fs.UnsupportedFileSystemEx ...

  10. 计算机网络|思维导图|自顶向下方法|MindMaps资料分享

    前言 那么这里博主先安利一下一些干货满满的专栏啦! 手撕数据结构https://blog.csdn.net/yu_cblog/category_11490888.html?spm=1001.2014. ...