滑动窗口算法专题
滑动窗口简介
滑动窗口就是利用单调性,配合同向双指针来优化暴力枚举的一种算法。
该算法主要有四个步骤
1. 先进进窗口
2. 判断条件,后续根据条件来判断是出窗口还是进窗口
3. 出窗口
4.更新结果,更新结果这个步骤是不确定的,应题目要求判断是在进窗口前更新结果还是出窗口前更新结果。
1. 长度最小的子数组
题目链接:209. 长度最小的子数组 - 力扣(LeetCode)

题目细节信息:
1.数组中都是正数 2.在数组中找到长度最小的子数组且子数组中的元素和小于target值
解法:滑动窗口
我们先定义一个left指针和right指针,left和right之间就是一个窗口。在定义一个变量sum来记录[left,right]区间的和。
根据题目要求,我们先确定第一个sum大于等于target值得右边界,所以我们先让right不断进窗口。
以题目中的实例1为例

接着我们根据sum的值来判断是否进窗口还是出窗口。sum的值无非会遇到两种情况。
当sum小于等于target的时候,我们先要更新最小长度和sum的值,接着在进窗口,即让left++
如下图:

之前left指向的元素已经不在窗口里面了,这也是理解出窗口的一个图解。
当sum小于target时,我们进窗口进行了,即right++
滑动窗口的正确性
为什么能判断滑动窗口是对的呢?
因为数组中的数据都是正数,当right找到第一个边界使sum大于等于target的值时,我们就没必要让right继续向后走了,因为数组中都是正数,right继续走下去,sum会变大,但是len也会变长,此时len肯定就不是我们要的结果了。所以不让right向后走,就避免了其他不符合题意情况的枚举了。
代码实现
代码一:我写的形式
public int minSubArrayLen(int target, int[] nums) {int n=nums.length;int left=0,right=0;int ret=Integer.MAX_VALUE;int sum=nums[right];while(right<n){if(sum<target){right++;//进窗口if(right<n){sum+=nums[right];}}else{ret=Math.min(ret,right-left+1);//更新长度最小值sum-=nums[left];//更新sum值left++;//出窗口}}return ret==Integer.MAX_VALUE?0:ret;}
代码二:
public int minSubArrayLen(int target, int[] nums) {int n=nums.length;int len=Integer.MAX_VALUE;int sum=0;for(int left=0,right=0;right<n;right++){//进窗口sum+=nums[right];while(sum>=target){//这里要用while循环len=Math.min(len,right-left+1);//更新最小长度sum-=nums[left];//更新sum的值left++;//出窗口}}return len==Integer.MAX_VALUE?0:len;}
2.无重复字符的最长字串
题目链接:3. 无重复字符的最长子串 - 力扣(LeetCode)

题目解析:在字符串中找到一个连续且无重复字符的子字符串,并返回其长度。
解法一:暴力枚举(会超时)
枚举从字符串的第一个字符开始往后,无重复字符的子串可以到什么位置,找出一个最大长度的即可。
因此,我们可以通过一个哈希表来记录往后枚举的过程中,字符是否出现重复的情况。
//时间复杂度O(n^2)
//空间复杂度O(1)
import java.util.*;
class Solution {public int lengthOfLongestSubstring(String s) {int len = s.length();int ret = 0;for(int i = 0; i < len; i++) {int[] hash = new int[128];for(int j = i; j < len; j++) {hash[s.charAt(j)]++;if(hash[s.charAt(j)] > 1) {break;}ret = Math.max(ret, j - i + 1);}}return ret;}
}
解法二:滑动窗口
此时,我们可以通过滑动窗口来优化上面的暴力枚举。
首先,先通过一种枚举的情况来分析,如下图

当我们枚举时,当right遇到第一个重复的字符a时,我们就不必要让right继续往后走了,因为前面的left的位置没变,当right继续往后走,left和right之间是一定有重复的字符的。
所以,此时,我们可以让right先固定在原地,先让left指针往后走,直到left指针跳过重复的字符,right才能继续完后走。
但是,当left往后走的时候,right没必要往回退到和left一样的位置,因为当left没有跳过第一个重复的字符时,right撑死只能走到第二个a的位置,且left往后走了,此时子串的长度肯定是比left没有往后走时短的。
两个指针没有回退,这时就可以使用滑动窗口了。
这里先解释下上面的hash数组的意思
这里hash数组的下标为字符串中字符的ASCII值,hash数组中的数据是该字符的出现次数。
滑动川口的解题步骤:
1.进窗口:让字符进入hash表中
2.判断和出窗口:判断该字符是否重复出现,如果重复出现,则出窗口,即将该字符从hash表中删除。
3.更新结果:这里是先进行判断后,才执行更新的操作。
代码实现:
时间复杂度:O(n)
空间复杂度:O(n)public int lengthOfLongestSubstring(String ss) {int n=ss.length();char[] s=ss.toCharArray();int[] hash=new int[128];int left=0,right=0,ret=0;while(right<n){hash[s[right]]++;//进窗口while(hash[s[right]]>1){//判断字符是否重复出现hash[s[left++]]--;//出窗口}ret=Math.max(ret,right-left+1);//更新结果right++;}return ret; }
3. 最大连续1的个数
题目链接:1004. 最大连续1的个数 III - 力扣(LeetCode)

题目解析:最多可以将数组中的k个0翻转为1,返回数组经过翻转后,数组中连续1的最大个数。
虽然题目中是要求我们翻转0,但是如果我们遇到0就将其翻转为1的话,接着进行新的枚举的时候,就又要将翻转过的0,重新翻转为0,此时,代码就会很难写,且很复杂。
其实,我们可以转换为求区间的长度,只要该区间的0的个数没有大于k个就行了。
解法一:暴力枚举+zero计数器
定义一个left和right指针,我们可以让left为起点向后枚举,定义一个zero变量来保存枚举过程中遇到0的个数 ,如果zero的值大于k,此时我们就可以让right指针停在该位置了,因为此时right如果继续走下去,left和right区间就是不符合题目要求了。
也就是说,此时以left为起点的枚举,得到的连续1的长度就是一个最优解了,此时就可以更新结果
所以,我们要换一个起点进行枚举,既让left++,接着让right回到left的位置,以新的left为起点继续,right继续向后枚举,重复上面的步骤。
解法二:滑动窗口
再暴力枚举上进一步优化,当我们让left++的时候,没必要将right重新指向left的位置,因为当zero的值大于k时,right撑死也时只能走到刚才停止的位置,只有我们left跳过一个0的时候,让zero减一,让zero的值小于k时,此时right才可以继续完后枚举。
此时,发现,left和right指针是同向运行,且不会退,我们就可以使用滑动窗口算法来解决该问题。
步骤一:进窗口
当right完后枚举时,遇到1就忽略,如果遇到0,就让zero的值加1
步骤二:判断+出窗口
当zero的值大于k时,我们就出窗口,也就时让left++,如果left遇到1就忽略,如果遇到0,就
让zero的值减1
步骤三:更新结果
此时,更新结果的步骤是在判断的步骤之后。
代码实现:
//时间复杂度:O(n)
//空间复杂度:O(1) public int longestOnes(int[] nums, int k) {int left=0,right=0,zero=0;int n=nums.length;int ret=0;while(right<n){if(nums[right]==1){right++;}else{right++;zero++;//出窗口}while(zero>k){//判断if(nums[left]==0){zero--;//进窗口}left++;}ret=Math.max(ret,right-left);//更新结果}return ret;}
注意:这里更新结果为什么不是right-left+1呢?因为我是再right++之后再更新长度,而不是再right++之前更新长度。
更简练版本:
public int longestOnes(int[] nums, int k) {int ret = 0;for(int left = 0, right = 0, zero = 0; right < nums.length; right++){if(nums[right] == 0) zero++; // 进窗⼝while(zero > k) // 判断if(nums[left++] == 0) zero--; // 出窗⼝ret = Math.max(ret, right - left + 1); // 更新结果}return ret;}
这个版本就是再right++之前更新长度,所以更新长度时是right-left+1
4.将x减到0的最小操作数
题目链接:1658. 将 x 减到 0 的最小操作数 - 力扣(LeetCode)

题目解析:
1.我们每次进行一次删减操作时,我们都要将数组最左边或最右边的元素删去,供下一次删减操作时使用
2.数组里面的都是正数
在该题中,只有数组里面全是正数,我们才能使用滑动窗口解决
分析:因为当数组里面有负数或者为0的数据时,当right到达第一个停止的位置时,当我们的tmp减去一个负数或者数据为0的数时,由于负数或0的缘故,会导致[left,right]区间的和有可能是等于或大于tmp的,所以,此时进行新的枚举时,right有可能会向前退,也有可能继续向后退。
解题思路转换:解决该题的时候,我们有时候会删去最左边的元素,有时候会删去最右边的元素,但是这种情况太复杂了,我们要转换思路。
正难则反:
题目要求我们找到数组两边使x值减为0的最小个数,我们就可以转换为求中间和为sum-x的最长子串。
解法一:暴力枚举
套两层for循环,遍历每一个子数组的情况,根据子数组的和是否等于target的值,我们就更新结果,接着break跳出一层循环。
解法二:滑动窗口
我们通过滑动窗口来优化枚举,我们每进行一次新的遍历的时候,我们发现没必要每次都让right回到left的位置,因为数组里面都是正数,当left++之后,[left,right]区间的和肯定是小于target的。
此时,发现left和right指针都不回退,此时就可以使用滑动窗口。
1.进窗口:tmp+=nums[right]
2.判断+出窗口:判断tmp的值是否大于target,如果大于出窗口,即nums-=nums[left++]
3.更新结果:当tmp的值等于target的时候,我们就可以更新结果。
//时间复杂度:O(n)
//空间复杂度:O(1)public int minOperations(int[] nums, int x) {int sum=0;for(int i=0;i<nums.length;i++){sum+=nums[i];}int ret=-1;int target=sum-x;//处理细节,if(target<0) return -1;for(int left=0,right=0,tmp=0;right<nums.length;right++){tmp+=nums[right];//进窗口while(tmp>target){//判断tmp-=nums[left++];//出窗口}if(tmp==target){ret=Math.max(ret,right-left+1);//更新结果}}if(ret==-1) return -1;//此时没有找到子数组和为target的子数组else return nums.length-ret;}
5.水果成篮(从这里开始比较认真)
题目连接:904. 水果成篮 - 力扣(LeetCode)

题目分析:有一个fruit数组,在数组中,不同元素的值代表不同的水果种类,相同元素的值代表水果的种类相同,我们有两个篮子,每个篮子只能装一种水果,一个篮子中装的水果数量没有限制。如果摘水果的过程中,一旦遇到与篮子中水果种类不同的水果树,就停止采摘,求这两个篮子能装的最大水果数量。
以上可以总结为一句话:找一个连续的最长子数组,该子数组中的水果种类不超出两种。
解法一:暴力枚举+哈希表
我们可以将每一个子数组的情况枚举出来,枚举的过程中,我们可以借助一个hash表来保存枚举过程中采摘水果的种类和数量。
我们用left为外层循环的标志,right为内层循环的标志
枚举的小细节:
1. 为了防止在[1,2,1]的情况下,right指针会造成数组越界,所以我们每次进行一次内循环时,要对right指针进行判断,是否越界。
2.当篮子中水果的种类也超出两种时,也应该跳出该内层循环
3.在每一次采摘水果之前,必须判断水果种类为2种时,下次采摘的水果是否为第三种水果,如果成立,则跳出内部循环
4.每次进行一次新的外部枚举时,我们也要将hash表中上次枚举保存水果的情况删掉。
代码
//空间复杂度:O(n)
//时间复杂度:O(n^2)public int totalFruit(int[] f) {Map<Integer, Integer> hash = new HashMap<Integer, Integer>();int ret = 0;for (int left = 0; left < f.length; left++) {for (int right = left; right < f.length; right++) {if (right == f.length || hash.size() > 2) {//判断数组是否越界和水果种类的数量break;}int in = f[right];if (hash.size() == 2 && !hash.containsKey(in)) {//摘水果之前的判断break;}hash.put(in, hash.getOrDefault(in, 0) + 1);ret = Math.max(ret, right - left + 1);}hash.clear();//在下次枚举之前,删除此次枚举的情况}return ret;}
解法二:滑动窗口
当我们进行新的left的枚举时,我们没必要让right重新回到left的位置,因为当left进行新的枚举时(left往后走),如果right重新返回到left指针的位置,往后枚举的时候,right会出现两种情况,第一种情况:right会停在在上一次left枚举时,right的最后枚举的位置或者超过right最后枚举的位置。也就是说,以新的left为新的起点,进行right的枚举时,right是一定会经过之前的枚举停下的位置的,所以,我们就不必要将right返回到left的位置。
通过上面的分析,发现left和right指针是同向双指针,这时我们就可以使用滑动窗口来解决这个问题。
解题步骤
1.定义left=0,right=0
2.进窗口:让hash[f[right]]++
3.判断+出窗口(一个循环):
当hash.size>2时,让hash[f[left]]--,同时让left++
4.更新长度
用哈希表来实现:
//时间复杂度:O(n)
//空间复杂度:O(n)public int totalFruit(int[] f) {Map<Integer,Integer> hash=new HashMap<Integer,Integer>();int ret=0;for(int left=0,right=0;right<f.length;right++){int in=f[right];hash.put(in,hash.getOrDefault(in,0)+1);//进窗口while(hash.size()>2){//判断int out=f[left];hash.put(out,hash.get(out)-1);//出窗口if(hash.get(out)==0){hash.remove(out);}left++;}ret=Math.max(ret,right-left+1);//更新长度}return ret;}
用数组来实现:
public int totalFruit(int[] f) {int n=f.length;int[] hash=new int[n+1];int ret=0;for(int left=0,right=0,kind=0;right<n;right++){int in=f[right];if(hash[in]==0){kind++;}hash[in]++;//进窗口while(kind>2){//判断int out=f[left];hash[out]--;//出窗口if(hash[out]==0){kind--;}left++;}ret=Math.max(ret,right-left+1);//更新长度}return ret;}
6.找出字符串中所有的异位字符串
题目链接:438. 找到字符串中所有字母异位词 - 力扣(LeetCode)

题目解析:再s字符串中找出p字符串中的所有异位字符串
异位字符串就是相同字符但是字符的顺序不一样组成的字符串,如abc、acb、bac、bca、cab和cba都是abc的异位字符串。
解决思路:滑动窗口+哈希表
如何判断两个字符串互为异位字符串呢?
第一种方法:我们可以将两个字符串按字典的顺序进行排序,接着判断这两个字符串是否相同就行,如果相同,那么就是异位字符串,如果不同,则不是异位字符串。
第二种方法:借用两个哈希表,hash1来存储p字符串,hash2来存储s字符串,最终判断两个哈希表是否相同,如果相同,那么互为异位字符串,如果不同,则不是异位字符串。
以下图为例

我们在s中找p的异位字符串,我们使用暴力枚举时,第一次枚举时, 当right-left+1长度为p.length()时,第一次枚举就结束了,如下图

此时第一次枚举就结束了,进行第二次枚举,让left++,同时让right返回到left的所处的位置

进行第二次枚举时,right继续走向right-left+1=p.length()的位置,此时发现right依然会进过之前的字符b和字符a

所以,每一次进行新的枚举,没必要让right回到left的位置,这样left和right都是同向双指针,这时,我们就可以用滑动窗口来解决问题。
进窗口:当right-left+1<=s.length时,hash2[in]++
判断+出窗口
如果right-left+1>p.length(),就出窗口,让hash2[out]--,同时让left++
更新结果
要判断是异位字符串在更新结果
代码实现
//时间复杂度:O(n+m)
//空间复杂度:O(n+m)public List<Integer> findAnagrams(String ss, String pp) {List<Integer> ret=new ArrayList<>();char[] s=ss.toCharArray();char[] p=pp.toCharArray();int[] hash1=new int[26];int[] hash2=new int[26];for(char ch:p){hash1[ch-'a']++;}for(int left=0,right=0;right<s.length;right++){char in=s[right];hash2[in-'a']++;//进窗口if(right-left+1>p.length){//判断char out=s[left];hash2[out-'a']--;//出窗口left++;}//更新结果if(right-left+1==p.length){//判断是否互为异位字符串boolean flag=true;for(int i=0;i<26;i++){if(hash1[i]!=hash2[i]){flag=false;}}if(flag==true) ret.add(left);//更新结果}}return ret;}
进一步优化,此时我们可以在更新结果那里优化一下,因为在更新结果那里我们需要遍历两个哈希表,时间复杂度还是太大了,我们可以通过一个变量count统计窗口中的有效字符个数。
下图解释了什么是有效字符,一次类推

前面我们用hash1统计了字符串p中的情况,用hash2统计了字符串s中的情况。
进窗口之后,我们对hash1[in]和hash2[in]进行比较,如果hash2[in]小于等于hash1[in],那么此时就可以认为该字符是一个有效字符,让count++
出窗口之前,我们对hash1[out]和hash2[out]进行比较,如果hash2[out]小于等于hash[out],此时就可以认为出去的字符是一个有效字符,让count--
最终在更新结果的时候,我们只要判断count是否等于p.length,如果等于p.length,就更新结果,如果不等于p.length,就不更新结果。
代码实现
public List<Integer> findAnagrams(String ss, String pp) {List<Integer> ret=new ArrayList<>();char[] s=ss.toCharArray();char[] p=pp.toCharArray();int[] hash1=new int[26];int[] hash2=new int[26];for(char ch:p){hash1[ch-'a']++;}for(int left=0,right=0,count=0;right<s.length;right++){char in=s[right];hash2[in-'a']++;//进窗口if(hash2[in-'a']<=hash1[in-'a']) count++;//更新有效字符个数if(right-left+1>p.length){//判断char out=s[left];if(hash2[out-'a']<=hash1[out-'a']) count--;//更新有效字符个数hash2[out-'a']--;//出窗口left++;}//更新结果if(count==p.length) ret.add(left);}return ret;}
7.串联所有单词的子串
题目链接:30. 串联所有单词的子串 - 力扣(LeetCode)
我们如果将words的每一个字符串看成一个整体,在以这个整体为单位去在s中找串联所有单词的子串,这时就跟找异位字符串差不多了。如下图
这道题的思路和第6题的解题思路差不多,这里讲不同点,假设words数组字符串的长度为m,数组的长度为len
1.right和left指针的位移
right和left一次位移的长度为m
2.hash表的不同
这里的哈希表存的是字符串的种类和数量,即Hash<String,Integer>
3.进行滑动窗口的次数
次数为m次
这里对不同点3进行解释
代码实现:
public List<Integer> findSubstring(String s, String[] words) {Map<String,Integer> hash1=new HashMap<String,Integer>();//存储wordsList<Integer> ret=new ArrayList<Integer>();for(String str:words){hash1.put(str,hash1.getOrDefault(str,0)+1);}int len=words[0].length(), m=words.length;for(int i=0;i<len;i++){//执行滑动窗口Map<String,Integer> hash2=new HashMap<String,Integer>();//存储sfor(int left=i,right=i,count=0;right+len<=s.length();right+=len){String in=s.substring(right,right+len);hash2.put(in,hash2.getOrDefault(in,0)+1);if(hash2.get(in)<=hash1.getOrDefault(in,0)) count++;//判断+出窗口while(right-left+1>m*len){String out=s.substring(left,left+len);if(hash2.get(out)<=hash1.getOrDefault(out,0)) count--;hash2.put(out,hash2.getOrDefault(out,0)-1);left+=len;}//更新结果if(count==m) ret.add(left);}}return ret;}
8.最小覆盖子串
题目链接:76. 最小覆盖子串 - 力扣(LeetCode)
题目分析:我们需要再字符串s中找一个子串,在这个子串中的字符种类,需要包含字符串t中所有字符类型,如果t中有了重复的字符,那么从s中找的子串的该字符的数量必须大于等于t中的重复字符的数量。
比如t为aba,那么在s中找的子串中,字符a的数量是不能小于t中a的字符数量。
解题思路:
首先,我们还是想到暴力枚举+hash表,我们将字符串中s的字符都枚举一遍,在枚举的过程中,如果遇到符合题目要求的子串,此时,就更新结果,接着立刻换一个字符进行新的枚举,以此类推下去。
优化思路:滑动窗口
如下图
此时,我们需要让left往后移动一步,当left++之后,left和right之间就会出现两种情况。
第一种情况:
如果left++之后,left和right之间的字符种类没有发生变化,当我们让right回到left的位置,进行新的枚举时,right还是会回到原来的位置。如下图
第二种情况:
如果left++之后,left和right之间的字符种类发生变化,当我们让right回到left的位置时,进行新的枚举,为了找到新的符合题目要求的子串,此时right肯定时跑到原来位置的后面。如下图:
所以,我们发现没必要每次都要将right返回到原来left的位置,我们只要根据每次left移动后的情况,根据情况来让right不动或者往后移动。
此时,发现left和right都是同向双指针,此时就可以使用滑动窗口。
在使用滑动窗口前,我们要用到两个哈希表,一个用来存储s字符串的情况,另一个用来存储t字符串的情况。
进窗口:hash2[in]++
判断+更新结果+出窗口:
判断:在s中找的子串是否符合题目要求,也就是hash2与hash1对应字符的数量是否一 样
跟新结果:由于我们这里找到一个符合题目要求的子串就要跟新结果,所以此处的跟新结果实在出窗口之前
出窗口:hash2[out]--
在进一步优化:更新结果
在更新结果那里,我们需要遍历两个哈希表来判断找的子串是否符合题目要求,每个哈希表都要遍历一遍,时间复杂度还是太大了,此时,我们可以通过count变量来统计hash1和hash2中完全相同的字符数量。
这里的完全相同是指数量和种类都相同。
在进窗口之后,如果hash2[in]==hash1[in],那么,我们认为在in在hash1和hash2中是完全相同的字符,则让count++
出窗口之前,如果如果hash2[in]==hash1[in],那么,我们认为在in在hash1和hash2中是完全相同的字符,则让count--
此时判断条件就变为count==hash1.size().
代码实现:
public String minWindow(String ss, String tt) {char[] s=ss.toCharArray();char[] t=tt.toCharArray();int[] hash1=new int[128];//存储tint[] hash2=new int[128];//存储s;int kinds=0;//记录t中有效字符的种类for(char ch:t){if(hash1[ch]==0) kinds++;hash1[ch]++;}int minlen=Integer.MAX_VALUE, begin=-1;for(int left=0,right=0,count=0;right<s.length;right++){//进窗口char in=s[right];hash2[in]++;if(hash2[in]==hash1[in]) count++;//判断+更新+出窗口while(kinds==count){//更新结果if(right-left+1<minlen){minlen=right-left+1;begin=left;}//出窗口char out=s[left];if(hash2[out]==hash1[out]) count--;hash2[out]--;//出窗口left++;//维护窗口}}if(begin==-1) return new String();else return ss.substring(begin,begin+minlen);}相关文章:
滑动窗口算法专题
滑动窗口简介 滑动窗口就是利用单调性,配合同向双指针来优化暴力枚举的一种算法。 该算法主要有四个步骤 1. 先进进窗口 2. 判断条件,后续根据条件来判断是出窗口还是进窗口 3. 出窗口 4.更新结果,更新结果这个步骤是不确定的,…...
基于Java的世界时区自动计算及时间生成方法
目录 前言 一、zoneinfo简介 1、zoneinfo是什么 2、zoneinfo有什么 二、在Java中进行时区转换 1、Java与zoneInfo 2、Java展示zoneInfo实例 3、Java获取时区ID 三、Java通过经纬度获取时区 1、通过经度求解偏移 2、通过偏移量计算时间 3、统一的处理算法 四、总结 …...
Excel + Notepad + CMD 命令行批量修改文件名
注意:该方式为直接修改原文件的文件名,不会生成新文件 新建Excel文件 A列:固定为 renB列:原文件名称C列:修改后保存的名称B列、C列,需要带文件后缀,为txt文件就是.txt结尾,为png图片…...
OpenGL 几何着色器高级应用
几何着色器高级应用 概念回顾 几何着色器(Geometry Shader)是 OpenGL 管线中的可选着色器阶段,位于顶点着色器(Vertex Shader) 和光栅化阶段 之间。 其核心功能是基于输入的图元(如点、线或三角形),生成新的图元,或对输入的图元进行修改。 几何着色器的执行是以图元…...
【Unity基础】Unity 2D实现拖拽功能的10种方法
方法1. 基于 Update 循环的拖拽方法 (DragDrop2D) 代码概述 using System.Collections; using System.Collections.Generic; using UnityEngine;public class DragDrop2D : MonoBehaviour {bool isDraggable;bool isDragging;Collider2D objectCollider;void Start(){objectC…...
duxapp中兼容多端的 BoxShadow 阴影组件
由于RN 安卓端对阴影的支持不太完善,使用这个组件可以实现阴影效果 在RN端是使用 react-native-fast-shadow 实现的 示例 import { BoxShadow, Text } from /duxui<BoxShadow><Text>这是内容</Text> </BoxShadow>Props 继承自Taro的View…...
服务器---centos上安装docker并使用docker配置jenkins
要在 Docker 中安装 Jenkins 并进行管理,可以按照以下步骤操作: 1. 安装 Docker 首先,确保你的系统已经安装了 Docker。如果尚未安装,可以使用以下命令进行安装: 在 CentOS 上安装 Docker sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://…...
Linux系统操作03|chmod、vim
上文: Linux系统操作02|基本命令-CSDN博客 目录 六、chmod:给文件设置权限 1、字母法 2、数字法(用的最多) 七、vim:代码编写和文本编辑 1、启动和退出 1️⃣启动 2️⃣退出 2、vim基本操作 六、chmod&#x…...
数据库同步中间件DBSyncer安装配置及使用
1、介绍 DBSyncer(英[dbsɪŋkɜː],美[dbsɪŋkɜː 简称dbs)是一款开源的数据同步中间件,提供MySQL、Oracle、SqlServer、PostgreSQL、Elasticsearch(ES)、Kafka、File、SQL等同步场景。支持上传插件自定义同步转换业务…...
虚幻5描边轮廓材质
很多游戏内都有这种描边效果,挺实用也挺好看的,简单复刻一下 效果演示: Linethickness可以控制轮廓线条的粗细 这样连完,然后放到网格体细节的覆层材质上即可 可以自己更改粗细大小和颜色...
ISP帳戶會記錄什麼資訊?
許多用戶並不知道ISP會記錄有關線上活動的大量資訊。從流覽歷史記錄到數據使用情況,ISP經常收集和保留用戶數據,引發一系列隱私問題。 ISP 記錄哪些數據? ISP可以根據其隱私政策記錄各種類型的資訊。常見的記錄數據包括: 1.流覽…...
Facebook如何避免因IP变动而封号?实用指南
随着Facebook在个人社交与商业推广中的广泛应用,越来越多的用户面临因“IP变动”而被封号的问题。尤其是跨境电商、广告运营者和多账号管理用户,这种情况可能严重影响正常使用和业务发展。那么,如何避免因IP变动导致的封号问题?本…...
EXCEL数据清洗的几个功能总结备忘
目录 0 参考教材 1 用EXCEL进行数据清洗的几个功能 2 删除重复值: 3 找到缺失值等 4 大小写转换 5 类型转化 6 识别空格 0 参考教材 精通EXCEL数据统计与分析,中国,李宗璋用EXCEL学统计学,日EXCEL统计分析与决策&#x…...
web网页连接MQTT,显示数据与下发控制命令
web网页连接MQTT,显示数据与下发控制命令 零、前言 在完成一些设备作品后,常常会因为没有一个上位机用来实时检测数据和下发命令而苦恼,在上一篇文章中提到了怎么白嫖阿里云服务器,并且在上面搭建了属于自己的web网站。那么现在…...
数据结构day3作业
一、完整功能【顺序表】的创建 【seqList.h】 #ifndef __SEQLIST_H__ #define __SEQLIST_H__#include <stdio.h> #include <string.h> #include <stdlib.h>//宏定义,线性表的最大容量 #define MAX 30//类型重定义,表示要存放数据的类…...
Android SDK 平台工具版本说明
Android SDK Platform-Tools 是 Android SDK 的一个组件。它包含与 Android 平台进行交互的工具,主要是 adb 和 fastboot。虽然 adb 是 Android 应用开发所必需的,但应用开发者通常仅使用 Studio 安装的副本。如果您想直接从命令行使用 adb 并且未安装 S…...
Sharding-jdbc基本使用步骤以及执行原理剖析
一、基本使用步骤 1、需求说明 使用sharding-jdbc完成对订单表的水平分表,通过快速入门的开发,了解sharding-jdbc使用方法 人工创建两张表,t_order_1和t_order_2,这两张表是订单表拆分后的表,通过sharding-jdbc向订…...
mysql重置root密码(适用于5.7和8.0)
今天出一期重置mysql root密码的教程,适用于5.7和8.0,在网上搜索了很多的教程发现都没有效果,浪费了很多时间,尝试了多次之后发现这种方式是最稳妥的,那么废话不多说,往下看: 目录 第一步&…...
Linux下SVN客户端保存账号密码
参考文章:解决:Linux上SVN 1.12版本以上无法直接存储明文密码_linux svn 保存密码-CSDN博客新版本svn使用gpg-agent存储密码-CSDN博客svn之无法让 SVN 存储密码,即使配置设置为允许_编程设计_ITGUEST 方法一:明文方式保存密码 首…...
centos7.9 gcc升级到11.2.1
一、信息查看 # cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) # gcc --version gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44) Copyright © 2015 Free Software Foundation, Inc. 本程序是自由软件;请参看源代码的版权声明。本软件没有任…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
