【java算法专场】滑动窗口(下)

目录

水果成篮

算法分析

算法步骤

示例

算法代码

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

算法分析

算法步骤

示例

算法代码

优化

算法代码

串联所有单词的子串

算法分析

算法步骤

示例

算法代码

 最小覆盖子串

算法分析

算法步骤

示例

算法代码


算法分析

这道题其实就是在数组中找连续的的最长子数组,且子数组里的不同数字不能超过两个。 如果采用暴力枚举数组中的每一个字串,并借助哈希表来存储子数组中有多少种水果,并且每种水果的数量有多少。时间复杂度会达到O(n),因此,可以在暴力枚举的举出上进行优化,使用滑动窗口来解决。

算法步骤

  1. 初始化:设置双指针leftright并初始化为0,表示滑动窗口的边界。设置一个空的HashMap来存储水果种类及数量。定义ans并初始化为0,用于记录能够采摘的数目。
  2. 右边界(right)移动:让right往右移动,并将nums[right]在HashMap中的数量+1
  3. 判断水果种类:当HashMap.size()>2时,说明此时采摘的水果中有3种,需要去除一种。此时就需要让left往右移动,并将nums[left]在HashMap中的数量-1,当nums[left]对应的数量为0时,说明此时已经将一种水果去除,调用 map.remove(fruits[left]),将水果移除。
  4. 更新结果:在右指针right遍历数组的时,每次都需要更新一下ans的值,判断ans此时的值是否比(right-left+1)大,若大于则进行更新。
  5. 遍历结束:当right遍历完数组,此时返回ans的值即可。

时间复杂度:O(n),n是数组长度,每个元素最多只会被遍历两次。在扩大窗口的时候,right会遍历一遍数组。在最坏情况下,left也只会遍历一遍数组。

空间复杂度:O(1),这里只用到了几个固定的变量,虽然使用了HashMap,但最多也只存储了三种。

示例

以[1,2,3,2,2]为例

第一步:初始化

让left=right=0,定义一个map(哈希表),初始化ans=0;

第二步:扩大窗口,判断种类

让right往右移,在map中不超过2种时,同时更新ans值。

 第三步:左指针移动

此时map中种类超过2种,需要移动左指针,直到map中某个水果的数量为0。将数量为0的水果从map中移除。

 第四步:右指针继续移动,重复二三步,直到右指针right遍历完数组。当遍历完数组,此时ans=4.即在数组中[2,3,2,2]。

第五步:返回结果,将ans=4返回。

算法代码

/**
 * 计算最长的水果数组段,其中只包含两种不同的水果。
 * 
 * @param fruits 水果数组,数组中的每个元素代表一种水果。
 * @return 返回最长的水果数组段的长度。
 */
public int totalFruit(int[] fruits) {
    /* 初始化结果变量为0,用于记录最长的水果数组段的长度 */
    int ans = 0;
    /* 初始化左指针为0,用于标记当前水果数组段的起始位置 */
    int left = 0;
    /* 初始化右指针为0,用于标记当前水果数组段的结束位置 */
    int right = 0;
    /* 使用HashMap来记录每种水果的数量,键为水果的类型,值为该类型水果的数量 */
    HashMap<Integer, Integer> map = new HashMap<>();
    /* 遍历水果数组,更新HashMap和计算最长数组段的长度 */
    for (; right < fruits.length; right++) {
        /* 将右指针指向的水果添加到HashMap中,如果该水果已存在,则数量加1 */
        map.put(fruits[right], map.getOrDefault(fruits[right], 0) + 1);
        /* 当HashMap中的水果种类超过2种时,需要缩小数组段直到满足条件 */
        while (map.size() > 2) {
            /* 从HashMap中减去左指针指向的水果的数量,如果数量减到0,则从HashMap中移除该水果 */
            map.put(fruits[left], map.getOrDefault(fruits[left], 0) - 1);
            if (map.get(fruits[left]) == 0) {
                map.remove(fruits[left]);
            }
            /* 左指针向右移动,缩小数组段 */
            left++;
        }
        /* 更新最长数组段的长度 */
        ans = Math.max(ans, right - left + 1);
    }
    /* 返回最长数组段的长度 */
    return ans;
}

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

算法分析

这道题题意说明了要在字符串s中找到所有p的异位词。所以这道题可以使用暴力枚举+哈希表,但是时间复杂度达到O(n^2),我们可以使用滑动窗口+哈希表来使用。

算法步骤

  1. 初始化:定义双指针leftright并初始化为0,将两个字符串s和p转化为字符数组ss和pp,且这里需要用到两个hash表,这里设置为hash1和hash2,hash1用来存放字符串p的字符个数,hash2用来后续的遍历操作。【这里由于限制了是小写字母,所以hash数组的大小可以设置为26】定义变量m记录p的长度。定义ans顺序表,用来存放在符合条件的子串的起始位置。
  2. 扩展右边界:右指针right往右移动,用变量in记录字符nums[right],将in字符存进hash2中,但需要注意在存放时需要让in-‘a’,即hash2[in-'a']。
  3. 处理窗口:由于这里是限定了窗口的大小,即字符串p的长度。所以当right-left+1大于m时,说明窗口过大,需要进行缩小窗口,让left往右移动一位,同时需要将out【这里定义变量out字符为hash2[left]】在hash2中➖1。当right-left+1==m,说明此时窗口大小刚好等于p的长度,调用equal方法来判断hash1和hash2是否相等,若相等,则将left添加到ans中

时间复杂度:O(n),n为s的长度,每个字符最多被访问2次。

空间复杂度:O(1),虽然使用hash1和hash2数组,但都是固定大小的,且使用的变量固定。

示例

算法代码

 /**
      * 查找字符串s中所有p的字母异位词的起始索引。
      *
      * @param s 输入的字符串
      * @param p 指定的模式字符串
      * @return 返回一个包含所有字母异位词起始索引的列表
      */
     public List<Integer> findAnagrams1(String s, String p) {
         List<Integer> ans = new ArrayList<>(); // 用于存储结果的列表
         int left = 0; // 窗口的左边界
         int right = 0; // 窗口的右边界
         char[] ss = s.toCharArray(); // 将字符串s转换为字符数组
         char[] pp = p.toCharArray(); // 将字符串p转换为字符数组
         int[] hash1 = new int[26]; // 用于存储模式字符串p的字符计数
         for (char ch : pp) hash1[ch - 'a']++; // 统计模式字符串p中每个字符的数量

         int[] hash2 = new int[26]; // 用于存储当前窗口中字符的计数
         int m = pp.length; // 模式字符串p的长度
         while (right < s.length()) { // 窗口右边界不超过字符串s的长度
             char in = ss[right]; // 当前纳入窗口的字符
             hash2[in - 'a']++; // 窗口内字符计数加一
             if (right - left + 1 > m) { // 当窗口大小超过模式字符串p的长度时
                 char out = ss[left++]; // 移除窗口最左边的字符
                 hash2[out - 'a']--; // 窗口内字符计数减一
             }
             if (right - left + 1 == m) { // 当窗口大小等于模式字符串p的长度时
                 if (Arrays.equals(hash1, hash2)) { // 比较窗口内字符计数和模式字符串的字符计数
                     ans.add(left); // 如果相同,则将窗口左边界添加到结果列表中
                 }
             }
             right++; // 窗口右边界向右移动
         }
         return ans; // 返回结果列表
     }

优化

当然,在上述中,若面对比较复杂的问题,不是最优解法,可以对其进行优化。

主要是第二、三步进行处理

在上述算法中,我们是将ss[right]的值直接放在hash2中,但我们可以进行优化:

  • 定义一个count,用来判断判断当前窗口是否符合条件,当count=m时,说明找到了符合条件的子串,将left添加到ans中即可;count++的前提条件是hash2中的计数小于等于hash1中的计数,才能让count++。
  • 当right-left+1>m,即窗口过大时,要缩小窗口,但同时需要判断此时以ss[left]为下标的hash2中的计数是否小于等于hash1中对应位置的计数,若小于,则需要让count--。

算法代码


     /**
      * 查找字符串s中所有p的字母异位词的起始索引。
      *
      * @param s 输入的字符串
      * @param p 指定的字母异位词模式
      * @return 返回一个包含所有字母异位词起始索引的列表
      */
     public List<Integer> findAnagrams(String s, String p) {
         List<Integer> ans = new ArrayList<>();
         char[] ss = s.toCharArray();
         char[] pp = p.toCharArray();

         // 初始化hash1数组,用于存储模式p中每个字符出现的次数
         int[] hash1 = new int[26];
         for (char ch : pp) {
             hash1[ch - 'a']++;
         }

         // count用于记录当前窗口中满足p中字符比例的子串数量
         int count = 0;
         int m = pp.length;
         // hash2数组用于存储当前窗口中每个字符出现的次数
         int[] hash2 = new int[26];
         int left = 0;
         int right = 0;

         // 滑动窗口遍历字符串s
         for (; right < s.length(); right++) {
             char in = ss[right];
             // 当前字符加入窗口,如果其出现次数不超过p中对应字符的次数,则count增加
             // 判断是否满足条件,进窗口
             if (++hash2[in - 'a'] <= hash1[in - 'a']) {
                 count++;
             }

             // 如果窗口大小超过了p的长度,则需要移除最左边的字符
             // 判断长度,
             if (right - left + 1 > m) {
                 char out = ss[left++];
                 // 移除字符,如果移除后窗口中该字符出现次数不超过p中对应字符的次数,则count减少
                 if (hash2[out - 'a']-- <= hash1[out - 'a']) {
                     count--;
                 }
             }

             // 如果当前窗口中满足p中字符比例的子串数量等于p的长度,则当前窗口起始索引加入结果列表
             if (count == m) {
                 ans.add(left);
             }
         }

         return ans;
     }

串联所有单词的子串

算法分析

这道题与前一道题优化算法的思路基本一样,要求在字符串s中找到words字符串数组中所有字符串任意顺序串联起来的子串。

算法步骤

  1. 初始化:设置双指针leftright并初始化为0;设置两个HahsMap<String,Integer>,map1用来存放words字符串数组中的字符串及其个数,map2用来存放s字符串中符合条件的字符串;设置ans顺序表,用来存放符合条件的子串起始位置。设置count并初始化为0,用来记录符合条件的子串个数;定义len并初始化为words[0].length()[即字符串数组中字符串的长度],定义m并初始化为words数组的长度
  2. 预处理:将words字符串数组中的字符串存放到map1中。
  3. 滑动窗口遍历字符串
  • 由于在s字符串中,我们不知道words数组中字符串在s中是在起始位置上开始的,所以根据len,可以有len种起始位置。示例:

  • 每个单词的长度为len,所以设置双指针在移动时,步长为len。
  • 遍历每一个有可能的起始位置i,并每次定义map2用来存放不同起始位置下的单词。 
  • 让left=right=i,count=0,移动窗口,并将分割出来的单词in放进map2中,判断in在map2中的数量是否小于等于map1的数量,若小于,则让count++;
  • 判断当前窗口的长度(right-left+1)是否大于字符串数组中所有字符串的总长度(len*m),若大于,说明窗口过大,需要将【left,left+len】位置的字符出窗口。需要出窗口的字符串out,需要判断是否在map2中的数量小于等于map1的数量,若小于,则让count--;当出完窗口后,需要让out在map2中对应的数量-1,再让left+=len;
  • 当count等于m【words数组的长度】,说明此时已经找到了符合条件的串联子串,将left添加到ans中。

4.返回结果:当遍历完所有可能的情况,此时返回结果ans即可。

示例

以s = "barfoothefoobarman", words = ["foo","bar"]为例

第一步:初始化,并预处理

在初始化完所需的变量之后,将words数组中的字符串存放到map1中,得到

map1={["foo",1],["bar",1]}

第二步:滑动窗口遍历s(此处只列举第一种起始位置情况)

  1. 此时left=right=i=0,count=0(此处len为3)
  2. 截断s中[right,right+len)位置的字符串作为in,in=“bar”,将in存放到map2中,map2={["bar",1]},并且判断一下in在map2中的数量是否小于等于在map1中的数量,若小于等于,则让count++;
  3. 判断窗口的大小(right-left+1=3-0+1=4<len*m=4*2=8,不需要进行出窗口操作。
  4. 由于count此时依旧为0,小于m=2,不满足条件,left不用添加到ans中。
  5. 重复上述操作。
  6. 第二次:map2={["bar",1],["foo",1]} count=2  添加left到ans中 ans=[0]
  7. 第三次:map2={["bar",1],["foo",1],["the",1]}  count=2 
  8. 出窗口:map2={["foo",1],["the",1]}  count=1 
  9. 第四次: map2={["foo",2],["the",1]}  count=1
  10. 出窗口: map2={["foo",1],["the",1]}  count=1
  11. 第五次: map2={["foo",1],["the",1],["bar",1]}  count=2  
  12. 出窗口:map2={["foo",1],["bar",1]}  count=2 添加left到ans中,此时left=9 ans=[0,9]
  13. 第六次:  map2={["foo",1],["bar",1],["man",1]}  count=2
  14. 出窗口:map1={["bar",1],["man",1]}  count=1
  15. 此时right已经走到s的末尾,遍历结束,返回结果ans=[0,9]。

算法代码

 /**
      * 查找所有包含给定单词数组中所有单词的子字符串的起始索引。
      *
      * @param s 输入的字符串。
      * @param words 给定的单词数组。
      * @return 包含所有单词的子字符串的起始索引列表。
      */
     public List<Integer> findSubstring(String s, String[] words) {
         // 用于存储结果的列表
         List<Integer> ans = new ArrayList<>();
         // 统计每个单词出现的次数
         // 借助hash表
         HashMap<String,Integer> map1=new HashMap<>();
         //统计words中有多少单词
         for(String word:words) map1.put(word,map1.getOrDefault(word,0)+1);
         //用于后序操作

         // 单词的长度
         int len=words[0].length();// 单词长度
         // 单词的数量
         int m=words.length;
         // 当前窗口中包含的所有单词的数量
         int count=0;
         // 窗口的左右边界
         int left=0;
         int right=0;
         // 遍历字符串s,寻找符合条件的子字符串
         for(int i=0;i<len;i++) {
             // 当前窗口中单词的统计信息
             HashMap<String, Integer> map2 = new HashMap<>();
             // 移动窗口,查找符合条件的子字符串
             for (left = i, right = i,count=0; right+ len <= s.length() ; right += len) {
                 // 窗口中的当前单词
                 //进窗口维护
                 String in = s.substring(right, right + len);
                 // 更新当前单词在窗口中的统计信息
                 map2.put(in, map2.getOrDefault(in, 0) + 1);
                 // 如果当前单词在窗口中的数量不超过其应有数量,则增加count
                 if (map2.get(in) <= map1.getOrDefault(in, 0)) count++;
                 // 如果窗口大小超过了最大允许值,则需要移除左边界上的单词
                 //出窗口
                 if (right - left + 1 > len*m) {
                     // 移除的单词
                     String out = s.substring(left, left + len);
                     // 如果移除的单词在窗口中的数量不超过其应有数量,则减少count
                     if (map2.get(out) <= map1.getOrDefault(out, 0)) count--;
                     // 更新窗口中移除单词的统计信息
                     map2.put(out, map2.get(out) - 1);
                     // 移动左边界
                     left += len;
                 }
                 // 如果当前窗口中包含了所有单词,则将左边界索引添加到结果列表中
                 if (count == words.length) ans.add(left);
             }
         }
         // 返回结果列表
         return ans;
     }

 最小覆盖子串

算法分析

本题要求在s中找到t的最小覆盖子串,我们可以使用暴力枚举+hash表来实现,但时间复杂度会达到O(n^2),我们可以在此进行优化,使用滑动窗口。

算法步骤

  1. 初始化:设置双指针leftright,并初始化为0作为滑动窗口的边界;将s和t字符串转化为字符数组ss和tt方便操作;设置两个hash表(hash1和hash2),长度为128,hash1用来统计t中的字符;设置begin并初始化为-1,mixLen初始化为Integer.MAX_VALUE,作为最小覆盖子串的起始位置以及末尾位置;定义count(计数器)并初始化为0,用来匹配符合条件的字符。

  2. 预处理:设置kind并初始化为0,用来计算t中的字符种类有多少种。将tt字符数组中的字符通过hash1进行计数,当hash[ch]为0时,kind++;

  3. 处理窗口:右指针移动,并将in【in=ss[right]】添加到hash2中,同时判断in在hash2中的数量是否与hash1的相同,若相同,则让count++。当计数器count等于kind时,说明已经找到了符合条件的子串,此时,若minLen==-1或者right-left+1<minLen时,更新begin=left和minLen=right-left+1;当添加完后,缩小窗口,让left往右移,若hash2[left]==hash1[left],需要让count--,同时让left++;寻找更小的覆盖子串。

  4. 重复上述操作,直到遍历完s。

  5. 返回结果:若minLen==-1,说明没有找到符合条件的子串,如不为0,则返回[begin,begin+minLen)的截断字符串。

时间复杂度:O(n),n为ss的长度,每个字符最多被遍历两次。

空间复杂度:O(1),虽然使用了hash,但长度是固定的。

示例

以s = "ADOBECODEBANC", t = "ABC"为例

第一步:初始化

  • left=right=0
  • 初始化hash1和hash2并设置长度为128.
  • 将s和t转化为字符数组ss和tt
  • kind=0,用于记录不同字符的种类,遍历数组tt并计数到hash1中,此处kind=3,hash['A']=1,hash['B']=1,hash['C']=1.

第二步:处理窗口

  1. 使用双指针left和right,扩大窗口,并将字符in计数到hash2中,若in在hash2的数量等于hash1的数量,则让count++;
  2. 当count=kind时,说明此事已经找到了匹配的覆盖子串,判断right-left+1<minLen或者minLen=-1时,则进行替换,让begin=left,minLen=right-left+1;当判断完之后,移除左窗口out,同时判断out在hash2和hash1的计数是否相等,若相等,则让count--。
  3. 重复上述操作,当right遍历完s字符串时,结束循环。
  4. 返回结果,此时,由于begin不为-1,根据begin和minLen,截取s中此位置的字符串,为“BANC”。

算法代码

  /**
      * 寻找字符串s中包含字符串t所有字符的最短子串。
      * @param s 原始字符串
      * @param t 目标字符串,需要在原始字符串中找到包含所有这些字符的最短子串
      * @return 返回最短子串的字符串,如果不存在则返回空字符串
      */
     public String minWindow(String s, String t) {
         // 初始化两个字符数组,用于统计字符串t和字符串s中字符出现的次数
         int[] hash1=new int[128];
         int[] hash2=new int[128];
         
         // 将字符串t转换为字符数组,方便后续处理
         char[] tt=t.toCharArray();
         
         // 计算字符串t中不同字符的数量
         int kind=0;
         for(char ch:tt){
             if(hash1[ch]++==0) kind++;
         }
         
         // 将字符串s转换为字符数组,方便后续处理
         char[] ss=s.toCharArray();
         
         // 初始化指针begin和minlen,begin用于标记最短子串的起始位置,minlen用于记录最短子串的长度
         int begin=-1;
         int minlen=Integer.MAX_VALUE;
         
         // 初始化滑动窗口的左指针left、右指针right和当前窗口中包含t中字符的数量count
         int left,right,count;
         for(left=0,right=0,count=0;right<ss.length;right++){
             char in=ss[right];
             // 当前字符在窗口中出现的次数等于在t中出现的次数时,count加1
             if(++hash2[in]==hash1[in]) count++;
             
             // 当窗口中包含了t中所有字符时
             while(count==kind){
                 // 更新最短子串的起始位置和长度
                 if(right-left+1<minlen||minlen==-1){
                     begin=left;
                     minlen=right-left+1;
                 }
                 // 移动窗口的左指针,并更新count和hash2数组
                 char out=ss[left++];
                 if(hash2[out]--==hash1[out]) count--;
             }
         }
         
         // 根据begin和minlen的值,返回最短子串或空字符串
         if(begin==-1){
             return  new String();
         }else{
             return s.substring(begin,begin+minlen);
         }
     }

以上就是本篇所有内容,滑动窗口的题目就先到这了,后序若有相关题目,将会更新!

若有不足,欢迎指正~ 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/797750.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python数据分析案例52——基于SSA-LSTM的风速预测(麻雀优化)

案例背景 又要开始更新时间序列水论文的系列的方法了&#xff0c;前面基于各种不同神经网络层&#xff0c;还有注意力机制做了一些缝合模型。 其实论文里面用的多的可能是优化算法和模态分解&#xff0c;这两个我还没出专门的例子&#xff0c;这几天正好出一个优化算法的例子来…

go-高效处理应用程序数据

一、背景 大型的应用程序为了后期的排障、运营等&#xff0c;会将一些请求、日志、性能指标等数据保存到存储系统中。为了满足这些需求&#xff0c;我们需要进行数据采集&#xff0c;将数据高效的传输到存储系统 二、问题 采集服务仅仅针对某个需求开发&#xff0c;需要修改…

树莓派pico入坑笔记,esp01/01s使用

目录 关于树莓派pico和circuitpython的更多玩法&#xff0c;请看树莓派pico专栏 说明 关于at指令 WiFi的at指令 UDP的at指令 样例程序 调试助手端输入指令 sta端程序 效果 进阶使用 库函数说明 样例代码 关于树莓派pico和circuitpython的更多玩法&#xff0c;请看树…

TensorFlow系列:第四讲:MobileNetV2实战

一. 加载数据集 编写工具类&#xff0c;实现数据集的加载 import keras""" 加载数据集工具类 """class DatasetLoader:def __init__(self, path_url, image_size(224, 224), batch_size32, class_modecategorical):self.path_url path_urlself…

H5的Canvas如何画N叉树数据结构

大家好。我是猿码叔叔&#xff0c;一位有着 5 年Java工作经验的北漂&#xff0c;业余时间喜欢瞎捣鼓&#xff0c;学习一些新东西来丰富自己。看过上一篇 Java 方法调用关系的老铁们&#xff0c;也许遗留了不少疑问&#xff0c;这Java方法调用关系可视化页面就这&#xff1f;这方…

护网HW面试——redis利用方式即复现

参考&#xff1a;https://xz.aliyun.com/t/13071 面试中经常会问到ssrf的打法&#xff0c;讲到ssrf那么就会讲到配合打内网的redis&#xff0c;本篇就介绍redis的打法。 未授权 原理&#xff1a; Redis默认情况下&#xff0c;会绑定在0.0.0.0:6379&#xff0c;如果没有采用相关…

基于SpringBoot的校园志愿者管理系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot框架 工具&#xff1a;MyEclipse、Tomcat 系统展示 首页 个人中心 志愿者管理 活动信息…

黑马头条微服务学习day01-环境搭建、SpringCloud微服务(注册发现、网关)

文章目录 项目介绍环境搭建项目背景业务功能技术栈说明 nacos服务器环境准备nacos安装 初始工程搭建环境准备主体结构 app登录需求分析表结构分析手动加密微服务搭建接口定义功能实现登录功能实现 Swagger使用app端网关nginx配置 项目介绍 环境搭建 项目背景 业务功能 技术栈说…

数据结构(Java):树二叉树

目录 1、树型结构 1.1 树的概念 1.2 如何判断树与非树 1.3 树的相关概念 1.4 树的表示形式 1.4.1 孩子兄弟表示法 2、二叉树 2.1 二叉树的概念 2.2 特殊的二叉树 2.3 二叉树的性质 2.4 二叉树的存储 2.5 二叉树的遍历 1、树型结构 1.1 树的概念 树型结构是一种非线…

MySQL复合查询(重点)

前面我们讲解的mysql表的查询都是对一张表进行查询&#xff0c;在实际开发中这远远不够。 基本查询回顾 查询工资高于500或岗位为MANAGER的雇员&#xff0c;同时还要满足他们的姓名首字母为大写的J mysql> select * from emp where (sal>500 or jobMANAGER) and ename l…

数据湖仓一体(一) 编译hudi

目录 一、大数据组件版本信息 二、数据湖仓架构 三、数据湖仓组件部署规划 四、编译hudi 一、大数据组件版本信息 hudi-0.14.1zookeeper-3.5.7seatunnel-2.3.4kafka_2.12-3.5.2hadoop-3.3.5mysql-5.7.28apache-hive-3.1.3spark-3.3.1flink-1.17.2apache-dolphinscheduler-3.1.9…

[Vulnhub] Sedna BuilderEngine-CMS+Kernel权限提升

信息收集 IP AddressOpening Ports192.168.8.104TCP:22, 53, 80, 110, 111, 139, 143, 445, 993, 995, 8080, 55679 $ nmap -p- 192.168.8.104 --min-rate 1000 -sC -sV PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2 …

C++20中的consteval说明符

在C20中&#xff0c;立即函数(immediate function)是指每次调用该函数都会直接或间接产生编译时常量表达式(constant expression)的函数。这些函数在其返回类型前使用consteval关键字进行声明。 立即函数是constexpr函数&#xff0c;具体情况取决于其要求。与constexpr相同&…

半小时获得一张ESG入门证书【详细中英文笔记一】

前些日子&#xff0c;有朋友转发了一则小红书的笔记给我&#xff0c; 标题是《半小时获CFI官方高颜值免费证书 ESG认证》。这对考证狂魔的我来说&#xff0c;必然不能错过啊&#xff0c;有免费的羊毛不薅白不薅。 ESG课程的 CFI 官方网址戳这里&#xff1a;CFI 于是信心满满的…

清华大学孙富春教授团队开发了多模态数字孪生环境,辅助机器人获得复杂的 3C 装配技能

中国是全球3C产品&#xff08;电脑、通信和消费电子&#xff09;的主要生产国&#xff0c;全球70%的3C产品产能集中在中国。3C智能制造装备的突破与产业化&#xff0c;对于提升我国制造产业的全球竞争力意义重大。 机器人在计算机、通信和消费电子 &#xff08;3C&#xff09; …

常用的设计模式和使用案例汇总

常用的设计模式和使用案例汇总 【一】常用的设计模式介绍【1】设计模式分类【2】软件设计七大原则(OOP原则) 【二】单例模式【1】介绍【2】饿汉式单例【3】懒汉式单例【4】静态内部类单例【5】枚举&#xff08;懒汉式&#xff09; 【三】工厂方法模式【1】简单工厂模式&#xf…

springboot 程序运行一段时间后收不到redis订阅的消息

springboot 程序运行一段时间后收不到redis订阅的消息 问题描述 程序启动后redis.user.two主题正常是可以收到消息的&#xff0c;发一条收一条&#xff0c;但是隔一段时间后&#xff1b;就收不到消息了&#xff1b; 此时如果你手动调用发送另外一个消息订阅redis.user.two2&…

vmware workstation 虚拟机安装

vmware workstation 虚拟机安装 VMware Workstation Pro是VMware&#xff08;威睿公司&#xff09;发布的一代虚拟机软件&#xff0c;中文名称一般称 为"VMware 工作站".它的主要功能是可以给用户在单一的桌面上同时运行不同的操作系统&#xff0c;它也是可进 行开发…

c# 容器变换

List<Tuple<int, double, bool>> 变为List<Tuple<int, bool>>集合 如果您有一个List<Tuple<int, double, bool>>并且您想要将其转换为一个List<Tuple<int, bool>>集合&#xff0c;忽略double值&#xff0c;您可以使用LINQ的S…