【算法系列篇】滑动窗口

在这里插入图片描述

文章目录

  • 前言
  • 什么是滑动窗口
  • 1.长度最小的子数组
    • 1.1 题目要求
    • 1.2 做题思路
  • 1.3 Java代码实现
  • 2.无重复字符的最长子串
    • 2.1 题目要求
    • 2.2 做题思路
    • 2.3 Java代码实现
  • 3.最大连续1的个数 III
    • 3.1 题目要求
    • 3.2 做题思路
    • 3.3 Java代码实现
  • 4.将x减到0的最小操作数
    • 4.1 题目要求
    • 4.2 做题思路
    • 4.3 Java代码实现
  • 5.水果成篮
    • 5.1 题目要求
    • 5.2 做题思路
    • 5.3 Java代码实现
  • 6.找到字符串中所有字母异位词
    • 6.1 题目要求
    • 6.2 做题思路
    • 6.3 Java代码实现
  • 7.串联所有单词的子串
    • 7.1 题目要求
    • 7.2 做题思路
    • 7.3 Java代码实现
  • 8.最小覆盖字串
    • 8.1 题目要求
    • 8.2 做题思路
    • 8.3 Java代码实现
  • 总结

前言

前面我们学习了什么是双指针,今天我将为大家分享一种特殊的双指针——滑动窗口,为什么说它是特殊的双指针呢?因为它也是有两个指针维护的,并且两个指针的移动方向是相同的,就跟我们平时生活中的窗口一样,两条边是往相同的方向移动的。

什么是滑动窗口

滑动窗口算法是一种用于解决数组或字符串相关问题的算法。它通过两个指针维护的一个窗口,在窗口内进行操作,并根据问题的要求移动窗口的起始位置或结束位置。

滑动窗口算法通常用于解决需要在连续子数组或子字符串中寻找最大值、最小值、满足特定条件的值等问题。它的基本思想是通过调整窗口的大小和位置,以便在不重复计算的情况下,高效地处理问题。

滑动窗口算法的步骤如下:

  1. 初始化窗口的起始位置和结束位置。
  2. 根据问题的要求,移动窗口的起始位置或结束位置。
  3. 在每次移动窗口时,根据窗口内的元素进行相应的操作,例如计算最大值、最小值、满足特定条件的值等。
  4. 重复步骤2和步骤3,直到窗口移动到数组或字符串的末尾。

滑动窗口算法的时间复杂度通常为O(n),其中n为数组或字符串的长度。它通过避免重复计算,提高了问题的解决效率。

我们通过几个例子来了解滑动窗口算法。

1.长度最小的子数组

https://leetcode.cn/problems/minimum-size-subarray-sum/

1.1 题目要求

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:

输入:target = 4, nums = [1,4,4]
输出:1

示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

提示:

1 <= target <= 109
1 <= nums.length <= 105
1 <= nums[i] <= 105
class Solution {public int minSubArrayLen(int target, int[] nums) {}
}

1.2 做题思路

我们先来看看,如果使用暴力解法该怎么做。分别以每个数字开始,向后找 和>=target的子数组。

在这里插入图片描述
暴力解法是通过两层循环,i 从 0开始,j 从 i+1 开始遍历整个数字,找到 和 >= target 的长度最小的子数组。并且这个和是每次循环都从 0 开始加的。

通过观察每次循环找到的长度最小的子数组,我们可以发现,left 指针和 right 指针都是向同一个方向向右移动的,暴力解法是每次循环结束之后 right 的位置就回到 left + 1 的位置,这样就多了很多重复的不必要的计算。所以滑动窗口就是在这个暴力解法的基础上进行优化的,每次 right 的指向不进行返回,而是继续向右滑动,那么为什么 right 的指向可以不用返回呢?因为每次循环 left 的指向都会向右移动一位,而你要想找的长度最小的子数组的和 >= target,你的 right 就必须也是向右移动或者不移动,但是绝对不会是向左移动(在数组元素都是正数的情况下),这种就是滑动窗口的基本特征

那么知道了使用滑动窗口这个算法的时候,我们来看看具体应该如何实现。定义一个 sum 变量,存储每次进窗口之后这个窗口元素的和,并且这个sum 不是每一次都是逐个累加而是用之前的 sum 加上进窗口的这个元素,当 sum >= target 的时候,就需要进行出窗口的操作,并且在出窗口的时候,还需要判断是否需要更新 ret 的值,继续寻找后面的长度最小的子数组,每出一个元素,sum 就需要减去这个出去的数,出窗口一直出到 sum < target,然后再进窗口,反复上面的操作,直到 right 到达数组末尾。

在这里插入图片描述

1.3 Java代码实现

class Solution {public int minSubArrayLen(int target, int[] nums) {int ret = Integer.MAX_VALUE;for(int left = 0,right = 0, sum = 0; right < nums.length; right++) {sum += nums[right];while(sum >= target) {ret = Math.min(ret,right - left + 1);sum -= nums[left++];}}return ret == Integer.MAX_VALUE ? 0 : ret;}
}

在这里插入图片描述

2.无重复字符的最长子串

https://leetcode.cn/problems/longest-substring-without-repeating-characters/

2.1 题目要求

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

提示:

0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成
class Solution {public int lengthOfLongestSubstring(String s) {}
}

2.2 做题思路

先来看看暴力解法如何解决
在这里插入图片描述
通过暴力解法,我们也可以发现,每次循环找到的无重复字符的最长子串它的 left 的 right 都是向右移动的,所以这个题目同样使用滑动窗口来解决。

因为这里求的是长度最长的无重复字符的子串,所以需要在进窗口的时候进行判断是否需要更新最大长度,而判断是否有重复的字符,我们可以借助哈希表来进行判断。

在这里插入图片描述

2.3 Java代码实现

class Solution {public int lengthOfLongestSubstring(String ss) {char[] s = ss.toCharArray();int[] hash = new int[128];int ret = 0;for(int left = 0, right = 0; right < s.length; right++) {char in = s[right];hash[in]++;if(hash[in] == 1) {ret = Math.max(ret,right - left + 1);}while(hash[in] > 1) {char out = s[left++];hash[out]--;}}return ret;}
}

在这里插入图片描述

3.最大连续1的个数 III

https://leetcode.cn/problems/max-consecutive-ones-iii/

3.1 题目要求

给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。

示例 1:

输入:nums = [1,1,1,0,0,0,1,1,1,1,0], K = 2
输出:6
解释:[1,1,1,0,0,1,1,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 6。

示例 2:

输入:nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
输出:10
解释:[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 10。

提示:

1 <= nums.length <= 105
nums[i] 不是 0 就是 1
0 <= k <= nums.length
class Solution {public int longestOnes(int[] nums, int k) {}
}

3.2 做题思路

很多人看到这个翻转0不知道啥意思,说通俗点就是0可以变成1,同样,先来看看暴力解法如何解决。

在这里插入图片描述

left 指针和 right 指针都是向右方向移动的,所以这道题目同样使用滑动窗口来解决。我们的判断条件是以窗口内0的数量为判断条件,并且求的是最大长度,所以是在进窗口的时候进行判断。

在这里插入图片描述

3.3 Java代码实现

class Solution {public int longestOnes(int[] nums, int k) {int ret = 0;for(int left = 0, right = 0,count = 0; right < nums.length; right++) {if(nums[right] == 0) count++;if(count <= k) {ret = Math.max(ret,right - left + 1);}while(count > k) {if(nums[left++] == 0) count--;}}return ret;}
}

在这里插入图片描述

4.将x减到0的最小操作数

https://leetcode.cn/problems/minimum-operations-to-reduce-x-to-zero/

4.1 题目要求

给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。

如果可以将 x 恰好 减到 0 ,返回 最小操作数 ;否则,返回 -1 。

示例 1:

输入:nums = [1,1,4,2,3], x = 5
输出:2
解释:最佳解决方案是移除后两个元素,将 x 减到 0 。

示例 2:

输入:nums = [5,6,7,8,9], x = 4
输出:-1

示例 3:

输入:nums = [3,2,20,1,1,3], x = 10
输出:5
解释:最佳解决方案是移除后三个元素和前两个元素(总共 5 次操作),将 x 减到 0 。

提示:

1 <= nums.length <= 105
1 <= nums[i] <= 104
1 <= x <= 109
class Solution {public int minOperations(int[] nums, int x) {}
}

4.2 做题思路

这道题目的意思就是:给定一个数字x,每次从数组的最左边或者最右边选择一个数减去,然后使x减到0的最少的操作数。这道题目如果从正面去做的话,会先的非常麻烦,不妨我们换一条思路,他求的是数组两边减去的最少的数字,不妨我们就求数组中间最长的子数组,使它们的和为数组所有元素的总和减去 target ,这样就能是数组的两侧的和为 target 并且长度最短。所以这个题目就跟前面的求数组长度最长的子数组是差不多的,就只是判断的地方不同,这里需要在出窗口之后判断是否需要更新ret的值,这里我就不给大家过多介绍了,关键就是能够知道这个思路。

4.3 Java代码实现

class Solution {public int minOperations(int[] nums, int x) {int sum = 0;for(int n : nums) sum += n;  //求数组所有元素的总和int target = sum - x;if(target < 0) return -1;int ret = -1;for(int left = 0, right = 0,sum1 = 0; right < nums.length; right++) {sum1 += nums[right];while(sum1 > target) {sum1 -= nums[left++];}if(sum1 == target) {ret = Math.max(ret,right - left + 1);}}return ret == -1 ? -1 : nums.length - ret;}
}

在这里插入图片描述

5.水果成篮

https://leetcode.cn/problems/fruit-into-baskets/

5.1 题目要求

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 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] 这两棵树。

示例 4:

输入:fruits = [3,3,3,1,2,1,1,2,3,3,4]
输出:5
解释:可以采摘 [1,2,1,1,2] 这五棵树。

提示:

1 <= fruits.length <= 105
0 <= fruits[i] < fruits.length
class Solution {public int totalFruit(int[] fruits) {}
}

5.2 做题思路

根据题目我们可以知道,只有两个篮子,只能装两种水果,并且每个篮子可以装的水果数是无限的,这道题跟子数组的问题是类似的,只是判断条件变成了水果的种类,进窗口的时候,添加水果的种类很简单,当这个种类的水果数量在之前为0时,就说明是一个新的种类,但是当我们出窗口的时候,如果某一种类的水果数量减为0的时候,就需要减去一种种类,那么我们如何统计某一水果的数量呢?哈希表,使用哈希表可以很高效的对某一种类的数量进行统计。

5.3 Java代码实现

class Solution {public int totalFruit(int[] fruits) {int ret = 1;int[] hash = new int[fruits.length];for(int left = 0, right = 0,kinds = 0; right < fruits.length; right++) {int in = fruits[right];if(hash[in]++ == 0) kinds++;if(kinds <= 2) {  //当水果的种类小于等于2的时候就需要做出判断ret = Math.max(ret,right - left + 1);}while(kinds > 2) {int out = fruits[left++];if(--hash[out] == 0) kinds--;}}return ret;}
}

在这里插入图片描述

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

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

6.1 题目要求

给定两个字符串 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 List<Integer> findAnagrams(String s, String p) {}
}

6.2 做题思路

这道题其实就相当于使用一个大小为 p 字符串长度的框从 s 字符串头部开始框 p 字符串长度的字符串,然后判断框起来的字符串是否是 p 字符串的异位词。

窗口中的大小是确定的,最终的窗口的大小是p字符串的长度,也就是说我们的判断条件就是窗口内的字符串是否是p字符串的异位词,这也是解决这道题的关键。那么我们应该如何解决呢?同样是使用两个哈希表,第一个哈希表统计p字符串每个单词出现的次数,当进窗口的时候,第二个哈希表中该字符出现的次数就加一,并且如果将这个字符添加进哈希表之后,该哈希表中对应字符出现的次数小于等于第一个哈希表对应字符出现的次数,就说明进窗口的这个字符为有效字符,我们使用 count 来记录有效字符的个数,count++,当 count 等于 p 字符串的长度时,就需要更新结果:将 left 的坐标添加进列表中。

6.3 Java代码实现

class Solution {public List<Integer> findAnagrams(String ss, String pp) {List<Integer> list = 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']++;int len = p.length;for(int left = 0, right = 0,count = 0; right < s.length; right++) {char in = s[right];if(++hash2[in - 'a'] <= hash1[in - 'a']) count++;if(right - left + 1 > len) {char out = s[left++];if(hash2[out - 'a']-- <= hash1[out - 'a']) count--;}if(count == len) {list.add(left);}}return list;}
}

在这里插入图片描述

7.串联所有单词的子串

https://leetcode.cn/problems/substring-with-concatenation-of-all-words/

7.1 题目要求

给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。

s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。

  • 例如,如果 words = [“ab”,“cd”,“ef”], 那么 “abcdef”, “abefcd”,“cdabef”, “cdefab”,“efabcd”, 和 “efcdab” 都是串联子串。 “acdbef” 不是串联子串,因为他不是任何 words 排列的连接。
    返回所有串联子串在 s 中的开始索引。你可以以 任意顺序 返回答案。

示例 1:

输入:s = "barfoothefoobarman", words = ["foo","bar"]
输出:[0,9]
解释:因为 words.length == 2 同时 words[i].length == 3,连接的子字符串的长度必须为 6。
子串 "barfoo" 开始位置是 0。它是 words 中以 ["bar","foo"] 顺序排列的连接。
子串 "foobar" 开始位置是 9。它是 words 中以 ["foo","bar"] 顺序排列的连接。
输出顺序无关紧要。返回 [9,0] 也是可以的。

示例 2:

输入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
输出:[]
解释:因为 words.length == 4 并且 words[i].length == 4,所以串联子串的长度必须为 16。
s 中没有子串长度为 16 并且等于 words 的任何顺序排列的连接。
所以我们返回一个空数组。

示例 3:

输入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]
输出:[6,9,12]
解释:因为 words.length == 3 并且 words[i].length == 3,所以串联子串的长度必须为 9。
子串 "foobarthe" 开始位置是 6。它是 words 中以 ["foo","bar","the"] 顺序排列的连接。
子串 "barthefoo" 开始位置是 9。它是 words 中以 ["bar","the","foo"] 顺序排列的连接。
子串 "thefoobar" 开始位置是 12。它是 words 中以 ["the","foo","bar"] 顺序排列的连接。

提示:

1 <= s.length <= 104
1 <= words.length <= 5000
1 <= words[i].length <= 30
words[i] 和 s 由小写英文字母组成
class Solution {public List<Integer> findSubstring(String s, String[] words) {}
}

7.2 做题思路

这道题目跟上面的一个题目是类似的,只是这里将字母换成了单词,所以我们可以仿照上面一个题的思路,将words数组中的每个字符串当作一个字母,s 字符串每与words数组中每个单词相同长度的字符串作为一个字母。

在这里插入图片描述
因为不仅可以从 b 开始,将字符数组分为多个字符串,还可以从a和r开始,所以这里我们需要进行 words 数组中每个单词长度的循环次数的操作。

这里的哈希表用数组就不容易模拟了,所以这里就需要用到 HashMap

7.3 Java代码实现

class Solution {public List<Integer> findSubstring(String s, String[] words) {List<Integer> list = new ArrayList<>();Map<String,Integer> map1 = new HashMap<>();for(String tmp : words) {map1.put(tmp,map1.getOrDefault(tmp,0) + 1);}int len = words.length;  //求words数组的大小int m = words[0].length();  //求words数组中每个单词的长度for(int i = 0; i < m; i++) {Map<String,Integer> map2 = new HashMap<>();for(int left = i, right = i, count = 0; right <= s.length()-m; right += m) {String in = s.substring(right,right + m);map2.put(in,map2.getOrDefault(in,0) + 1);if(map2.get(in) <= map1.getOrDefault(in,0)) count++;if(right - left + 1 > len * m) {String out = s.substring(left,left + m);if(map2.get(out) <= map1.getOrDefault(out,0)) count--;map2.put(out,map2.get(out) - 1);left += m;}if(count == len) list.add(left);}}return list;}
}

在这里插入图片描述

8.最小覆盖字串

https://leetcode.cn/problems/minimum-window-substring/

8.1 题目要求

给你一个字符串 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 的子串中,
因此没有符合条件的子字符串,返回空字符串。

提示:

m == s.length
n == t.length
1 <= m, n <= 105
s 和 t 由英文字母组成
class Solution {public String minWindow(String s, String t) {}
}

8.2 做题思路

因为这道题目中说了,可以出现重复的字符,所以这道题的判断条件就是窗口中是否含有 t 字符串中的所有字符,并且窗口中的每个字符出现的次数必须大于 t 字符串中每个字符出现的次数。那么这道题的步骤主要分为两步:

  1. 在s字符串中,找到含有 t 字符串中含有的所有字符的窗口
  2. 在这个窗口中找长度最小的子串

在这里插入图片描述

8.3 Java代码实现

class Solution {public String minWindow(String ss, String tt) {char[] s = ss.toCharArray();char[] t = tt.toCharArray();int[] hash1 = new int[128];int[] hash2 = new int[128];int kinds = 0;for(char ch : t) {if(hash1[ch]++ == 0) kinds++;}int begin = -1;int minLen = Integer.MAX_VALUE;for(int left = 0, right = 0,count = 0; right < s.length; right++) {char in = s[right];if(++hash2[in] == hash1[in]) count++;while(count == kinds) {if(right - left + 1 < minLen) {begin = left;minLen = right - left + 1;}char out = s[left++];if(hash2[out]-- == hash1[out]) count--;}}if(begin == -1) return new String();else return ss.substring(begin,begin + minLen);}
}

在这里插入图片描述

总结

当涉及到解决子串或子数组的问题时,滑动窗口算法是一种非常有效的技术。它通过维护一个窗口,该窗口在字符串或数组上滑动,以解决特定问题。

滑动窗口算法的主要思想是使用两个指针,一个指向窗口的起始位置,另一个指向窗口的结束位置。通过调整这两个指针,可以扩展或收缩窗口,以找到所需的解。算法的关键是确定窗口的移动规则以及如何在移动过程中更新解。

下面是滑动窗口算法的一般步骤:

  1. 初始化窗口的起始指针和结束指针,使其指向合理的位置。
  2. 进入一个循环,不断尝试扩展窗口,直到窗口无法再扩展为止。
  3. 在每次窗口移动时,更新解(如果有必要)。
  4. 如果窗口仍然满足问题的要求,尝试收缩窗口,以寻找更优的解。
  5. 重复步骤3和4,直到窗口完全收缩并处理完所有元素。

滑动窗口算法的优点是其时间复杂度通常是线性的,因为它避免了对每个子串或子数组的重复计算,节约了计算资源。它也通常可以在O(1)的空间复杂度下完成。

滑动窗口算法常用于解决一些经典问题,例如字符串匹配、子数组和子串求和、最长/最短子数组等。通过适当定义窗口的移动规则和解的更新方式,可以针对不同的具体问题进行定制化的实现。

总结而言,滑动窗口算法是一种高效的解决子串或子数组问题的方法。它的核心思想是通过维护一个窗口,在问题的限定条件下移动窗口的起始和结束指针,同时利用解的特性来优化计算过程。使用滑动窗口算法可以提高问题的解决效率,并减少不必要的计算。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【仿写框架之仿写Tomact】四、封装HttpRequest对象(属性映射http请求报文)、HttpResponse对象(属性映射http响应报文)

文章目录 1、创建HttpRequest对象2、创建HttpResponse对象 1、创建HttpRequest对象 HttpRequest对象中的属性与HTTP协议中的内容对应&#xff0c;用于后序servlet从request中获取请求中的参数。 参照http请求报文&#xff1a; import java.io.BufferedReader; import java…

配置使用Gitee账号认证登录Grafana

三方社会化身份源 集成gitee第三方登录 第三方登录的原理 所谓第三方登录&#xff0c;实质就是 OAuth 授权。用户想要登录 A 网站&#xff0c;A 网站让用户提供第三方网站的数据&#xff0c;证明自己的身份。获取第三方网站的身份数据&#xff0c;就需要 OAuth 授权。 举例来…

ubuntu上使用osg3.2+osgearth2.9

一、介绍 在ubuntu上使用osgearth加载三维数字地球&#xff0c;首先要有osg和osgearth的库&#xff0c;这些可以直接使用apt-get下载安装&#xff0c;但是版本有些老&#xff0c;如果需要新版本的就需要自己编译。 #查看现有版本 sudo apt-cache madison openscenegraph #安装…

Python写一个创意五子棋游戏

前言 在本教程中&#xff0c;我们将使用Python写一个创意五子棋游戏 &#x1f4dd;个人主页→数据挖掘博主ZTLJQ的主页 个人推荐python学习系列&#xff1a; ☄️爬虫JS逆向系列专栏 - 爬虫逆向教学 ☄️python系列专栏 - 从零开始学python 首先 GomokuGame 类的构造函数 __ini…

小程序 CSS-in-JS 和原子化的另一种选择

小程序 CSS-in-JS 和原子化的另一种选择 小程序 CSS-in-JS 和原子化的另一种选择 介绍快速开始 pandacss 安装和配置 0. 安装和初始化 pandacss1. 配置 postcss2. 检查你的 panda.config.ts3. 修改 package.json 脚本4. 全局 css 注册 pandacss5. 配置的优化与别名 weapp-pand…

LeetCode 周赛上分之旅 #40 结合特征压缩的数位 DP 问题

⭐️ 本文已收录到 AndroidFamily&#xff0c;技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 和 BaguTree Pro 知识星球提问。 学习数据结构与算法的关键在于掌握问题背后的算法思维框架&#xff0c;你的思考越抽象&#xff0c;它能覆盖的问题域就越广&#xff0c;理解难度…

07_缓存预热缓存雪崩缓存击穿缓存穿透

缓存预热&缓存雪崩&缓存击穿&缓存穿透 一、缓存预热 提前将数据从数据库同步到redis。 在程序启动的时候&#xff0c;直接将数据刷新到redis懒加载&#xff0c;用户访问的时候&#xff0c;第一次查询数据库&#xff0c;然后将数据写入redis 二、缓存雪崩 发生情…

Roxy-Wi 命令执行漏洞复现

漏洞描述 Roxy-WI是开源的一款用于管理 Haproxy、Nginx 和 Keepalived 服务器的 Web 界面 Roxy-WI 6.1.1.0 之前的版本存在安全漏洞,该漏洞源于系统命令可以通过 subprocess_execute 函数远程运行,远程攻击者利用该漏洞可以执行远程代码。 免责声明 技术文章仅供参考,任…

小程序前台Boot后台校园卡资金管理系统java web学校进销存食堂挂失jsp源代码

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 小程序前台Boot后台校园卡资金管理系统 系统有2权限&…

Nuxt3_1_路由+页面+组件+资源+样式 使用及实例

1、 简介 1.1 开发必备 node版本 v16.10.0 我使用的是16.14.0编辑器推荐使用Volar Extension 的VS code插件Terminal 运行nuxt指令 1.2 环境搭建 安装项目&#xff1a; npx nuxilatest init [first_nuxt3]进入项目目录&#xff1a; cd [first_nuxt3]安装依赖&#xff1a;n…

【蓝桥杯】[递归]母牛的故事

原题链接&#xff1a;https://www.dotcpp.com/oj/problem1004.html 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 我们列一个年份和母牛数量的表格&#xff1a; 通过观察&#xff0c;找规律&#xff0c;我们发现&#xff1a; 当年份小于等于4时&…

如何在出差期间远程访问企业ERP系统?内网穿透解决您的难题!

文章目录 概述1.查看象过河服务端端口2.内网穿透3. 异地公网连接4. 固定公网地址4.1 保留一个固定TCP地址4.2 配置固定TCP地址 5. 使用固定地址连接 概述 ERP系统对于企业来说重要性不言而喻&#xff0c;不管是财务、生产、销售还是采购&#xff0c;都需要用到ERP系统来协助。…

JVM前世今生之JVM内存模型

JVM内存模型所指的是JVM运行时区域&#xff0c;该区域分为两大块 线程共享区域 堆内存、方法区&#xff0c;即所有线程都能访问该区域&#xff0c;随着虚拟机和GC创建和销毁 线程独占区域 虚拟机栈、本地方法栈、程序计数器&#xff0c;即每个线程都有自己独立的区域&#…

华盛顿大学Baker实验室率先设计出双稳态结构蛋白质

在蛋白质世界&#xff0c;“结构决定功能”是一条基本原则。因此&#xff0c;很多人可能认为&#xff0c;一个蛋白质就应该有一个唯一确定的结构&#xff0c;使得它能够去执行确定的生物学功能。其实&#xff0c;在真实的世界中&#xff0c;蛋白质大多都是处于一种不断起伏的动…

依赖预构建与静态资源处理

依赖预构建 vite是一个基于浏览器原生ES-Module的前端构建工具。 当你首次启动vite的时候&#xff0c;vite会在本地加载你的站点之前预构建项目依赖。 原因&#xff1a; CommonJS和UMD兼容性&#xff1a;在开发阶段中&#xff0c;Vite的开发服务器将所有的代码视为原生ES模块。…

unity 之 GetComponent 获取游戏对象上组件实例方法

GetComponent 简单介绍 GetComponent 是Unity引擎中用于获取游戏对象上组件实例的方法。它允许您从游戏对象中获取特定类型的组件&#xff0c;以便在脚本中进行操作和交互。 GetComponent< ComponentType >(): 这是一个泛型方法&#xff0c;用于从当前游戏对象上获取指定…

【⑫MySQL | 约束(二)】外键 | 默认值 | 检查约束 — 综合案例

前言 ✨欢迎来到小K的MySQL专栏&#xff0c;本节将为大家带来MySQL外键 | 默认值 | 检查约束 以及综合案例的分享✨ 目录 前言6. 外键约束(FOREIGN KEY,FK)7. 默认值约束和检查约束8. 综合实战总结 6. 外键约束(FOREIGN KEY,FK) 前面介绍的完整性约束都是在单表中进行设置&…

七夕前的爱心代码!

话不多说上代码&#xff01; import turtle as tu import random as ratu.setup(1.0, 1.0) tu.screensize(1.0, 1.0) tu.bgcolor(black) t tu.Pen() t.ht() colors [pink, hotpink, deeppink, lightpink, red, purple, violet, magenta]def draw_star(x, y, size, color):t.…

HASH索引,AVL树,B树,B+树的区别?

提前声明&#xff0c;本篇文章是我对我之前B树那篇文章的追加部分和补充的知识点&#xff0c;建议各位在看本篇文章的时候时已经了解了数据库索引B树的基本原理&#xff0c;否则有些地方可能理解起来会多一些难度哦&#xff01; 深入理解索引B树的基本原理_程序猿ZhangSir的博…