【优选算法篇】踏入算法的深邃乐章:滑动窗口的极致探秘

文章目录

  • C++ 滑动窗口详解:进阶题解与思维分析
    • 前言
    • 第二章:进阶挑战
      • 2.1 水果成篮
        • 解法一:滑动窗口
        • 解法二:滑动窗口 + 数组模拟哈希表
        • 复杂度分析:
        • 图解分析:
          • 示例:
          • 滑动窗口执行过程图解:
        • 详细说明:
      • 2.2 找到字符串中所有字母异位词
        • 解法:滑动窗口 + 哈希表
        • 复杂度分析:
        • 图解分析:
          • 滑动窗口执行过程图解:
        • 详细说明:
      • 2.3 串联所有单词的子串
        • 解法:滑动窗口+哈希表
        • 复杂度分析:
        • 图解分析:
          • 滑动窗口执行过程图解:
        • 详细说明:
      • 2.4 最小覆盖子串
        • 解法:滑动窗口 + 哈希表
        • 复杂度分析:
        • 图解分析:
          • 滑动窗口执行过程图解:
        • 详细说明:
    • 写在最后

C++ 滑动窗口详解:进阶题解与思维分析

💬 欢迎讨论:如有疑问或见解,欢迎在评论区留言互动。

👍 点赞、收藏与分享:如觉得这篇文章对您有帮助,请点赞、收藏并分享!
🚀 分享给更多人:欢迎分享给更多对 C++ 感兴趣的朋友,一起学习滑动窗口的基础与进阶!


前言

接上篇【优选算法篇】编织算法的流动诗篇:滑动窗口的轻盈之美

在算法的世界中,滑动窗口是一种极具优雅和灵活性的算法技巧。在上一章中,我们通过几个经典问题初步领略了滑动窗口的强大之处。然而,算法的探索并没有止步于此。随着问题的复杂性逐渐提升,滑动窗口的应用场景也变得更加丰富多样。在这篇博客中,我们将继续深入探讨滑动窗口的进阶应用。通过更加灵活的策略、动态调整窗口,我们将解决一系列复杂的算法挑战,进一步揭示滑动窗口的无限可能。

接下来,让我们步入滑动窗口的进阶领域,探索更多算法之美。


第二章:进阶挑战

2.1 水果成篮

题目链接:904. 水果成篮

题目描述
你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果种类。你想要尽可能多地收集水果,但是有一些规则:

  • 你有两个篮子,每个篮子只能装一种类型的水果,篮子的容量无限制。
  • 你可以选择任意一棵树开始采摘,但必须从这棵树开始依次向右采摘每棵树上的水果。
  • 一旦遇到某棵树上的水果不符合篮子中的水果种类,你必须停止采摘。

返回你能采摘的最多的水果数量。

示例 1

  • 输入:fruits = [1,2,1]
  • 输出:3
  • 解释:你可以采摘所有 3 棵树上的水果。

示例 2

  • 输入:fruits = [0,1,2,2]
  • 输出:3
  • 解释:你只能采摘 [1,2,2] 这三棵树的水果。如果从第 1 棵树开始采摘,只能采摘到 [0,1]。

示例 3

  • 输入: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

解法一:滑动窗口

算法思路

本题是典型的滑动窗口问题。要求我们找到一个连续区间,其中只能有两种不同种类的水果(即至多两个不同元素)。通过滑动窗口,我们可以动态调整区间大小,保持窗口内水果种类不超过两种。

具体步骤:

  1. 用一个哈希表 hash 记录滑动窗口内的水果种类和数量。
  2. 滑动窗口的右边界 right 向右移动,每次将新水果加入哈希表。
  3. 如果哈希表中记录的水果种类超过两个,左边界 left 开始向右移动,直到窗口内水果种类不超过两个为止。
  4. 在每次满足条件时,更新最大收集到的水果数量 ret

算法流程

  1. 初始化哈希表 hash,左右指针 leftright,以及记录结果的变量 ret
  2. 遍历数组 fruits,对每个水果进行如下操作:
    • right 指向的水果加入哈希表,统计频次。
    • 如果哈希表的大小超过 2,左指针 left 向右移动,同时更新哈希表,直到哈希表中只有两种水果。
    • 在满足条件时,更新最大采摘数量 ret
  3. 返回结果。

代码实现

#include <unordered_map>
#include <vector>
using namespace std;class Solution {
public:int totalFruit(vector<int>& fruits) {unordered_map<int, int> hash; // 统计滑动窗口内水果的种类和数量int ret = 0; // 记录最大水果数量int left = 0; // 左指针for (int right = 0; right < fruits.size(); ++right) {hash[fruits[right]]++; // 右指针扩展窗口,加入新水果// 如果种类超过 2,收缩窗口while (hash.size() > 2) {hash[fruits[left]]--; // 移除左边水果if (hash[fruits[left]] == 0) {hash.erase(fruits[left]); // 种类为 0,删除该水果}left++; // 左指针向右移动}ret = max(ret, right - left + 1); // 更新最大水果数量}return ret;}
};

解法二:滑动窗口 + 数组模拟哈希表

算法思路

利用数组 hash 来代替哈希表,用水果种类的值直接作为数组下标,来统计每种水果的数量。这种方式效率更高,因为直接使用数组的下标访问比哈希表操作更快。

代码实现

class Solution {
public:int totalFruit(vector<int>& fruits) {int hash[100001] = {0};  // 数组模拟哈希表int ret = 0;             // 记录结果int left = 0;            // 左指针int kinds = 0;           // 记录当前窗口内的水果种类数for (int right = 0; right < fruits.size(); ++right) {if (hash[fruits[right]] == 0) kinds++;  // 新种类水果进入窗口hash[fruits[right]]++;  // 统计数量// 当水果种类超过 2 时,收缩窗口while (kinds > 2) {hash[fruits[left]]--;  // 移除左边水果if (hash[fruits[left]] == 0) kinds--;  // 种类数量减少left++;  // 左指针右移}ret = max(ret, right - left + 1);  // 更新最大水果数量}return ret;}
};

复杂度分析:
  • 时间复杂度O(n),每个元素最多被左右指针访问两次。
  • 空间复杂度O(n),哈希表或数组最多存储 n 种水果的频次。

图解分析:
示例:
  • 输入fruits = [3,3,3,1,2,1,1,2,3,3,4]
  • 输出5
  • 解释:你可以采摘 [1,2,1,1,2] 这五棵树的水果。

滑动窗口执行过程图解:
IterationLeftRight水果种类窗口内水果窗口大小最大结果
1001[3]11
2011[3, 3]22
3021[3, 3, 3]33
4032[3, 3, 3, 1]44
5043[3, 3, 3, 1, 2]55
6352[1, 2, 1]35
7362[1, 2, 1, 1]45
8372[1, 2, 1, 1, 2]55
9782[2, 3]25
10792[2, 3, 3]35
118102[3, 3, 4]35

详细说明:
  1. Iteration 1-3Right 扩展到 2,窗口内只有一种水果 3,因此子数组为 [3,3,3],长度为 3
  2. Iteration 4:加入水果 1,种类增加到两种,窗口变为 [3,3,3,1],长度更新为 4
  3. Iteration 5:加入水果 2,种类增加到三种,此时需要调整窗口,移动 Left,直到只剩两种水果。经过调整,窗口变为 [1,2,1]
  4. Iteration 6-8:继续右移 Right,窗口内的水果种类保持为两种,最大长度更新为 5,子数组为 [1,2,1,1,2]
  5. Iteration 9-11:加入水果 3,水果种类再次超出限制,继续收缩窗口,最终找到的最大子数组长度为 5

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

题目链接:438. 找到字符串中所有字母异位词

题目描述

给定两个字符串 sp,找到 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 * 10^4
  • sp 仅包含小写字母。

解法:滑动窗口 + 哈希表

算法思路

这道题要求我们在字符串 s 中找到所有与字符串 p异位词 对应的子串。由于异位词由相同字母组成且长度与 p 相同,因此我们可以使用滑动窗口来解决这一问题。

  1. 窗口大小固定
    因为异位词的长度一定与字符串 p 的长度相同,所以我们构造一个长度为 p.size() 的滑动窗口,每次右移窗口,动态维护窗口内每个字母的出现频次。

  2. 频次匹配判断
    通过两个大小为 26 的数组来统计字母出现的次数,分别用于存储当前窗口内字母频次(hash2)和 p 中的字母频次(hash1)。当两个数组的内容相同,说明当前窗口就是 p 的一个异位词。

  3. 窗口移动
    每次右移窗口时,更新窗口内字母的频次。如果窗口超过 p.size(),需要将最左边的字母移出窗口。若在滑动过程中,两个数组的内容始终保持一致,那么我们记录该窗口的起始索引。


算法流程

  1. 初始化两个大小为 26 的数组 hash1hash2,分别记录 p 中字母的频次和窗口中字母的频次。
  2. 遍历字符串 s,使用右指针 right 逐渐扩大窗口:
    • 每次将窗口右端的字母加入窗口,并更新其频次。
    • 若窗口超过 p.size(),则需要从左侧移出一个字母,并更新频次。
  3. hash1hash2 相等时,说明当前窗口是 p 的一个异位词,记录其起始位置。
    因为直接比较两个哈希表时间复杂度很高,这里我们想到了一种优化方式,要判断窗口字符串是否是异位词,我们只需要判断同一种字符在两个字符串中出现的次数是否一样即可,这里我们使用count来统计有效字符的个数即可轻松判断窗口字符串是否是p的异位词
  4. 最后返回所有满足条件的起始位置列表。

代码实现

#include <vector>
using namespace std;class Solution {
public:vector<int> findAnagrams(string s, string p) {vector<int> ret;int hash1[26] = { 0 }; // 统计字符串 p 中每个字符出现的个数for(auto ch : p) hash1[ch - 'a']++; int hash2[26] = { 0 }; // 统计窗口里面的每一个字符出现的个数int m = p.size();for(int left = 0, right = 0, count = 0; right < s.size(); right++) {char in = s[right];// 进窗口 + 维护 countif(++hash2[in - 'a'] <= hash1[in - 'a']) count++;if(right - left + 1 > m) {  // 判断窗口是否需要收缩char out = s[left++];// 出窗口 + 维护 countif(hash2[out - 'a']-- <= hash1[out - 'a']) count--;}// 更新结果if(count == m) ret.push_back(left);}return ret;}
};

这里面count是指有效字符的个数,很巧妙的判断滑动窗口里的字符串是否满足条件


复杂度分析:
  • 时间复杂度O(n),每个字符最多被左右指针访问两次,因此时间复杂度为线性。
  • 空间复杂度O(1),只需要常数级别的额外空间用于存储两个固定大小的数组。

图解分析:

假设输入为 s = "cbaebabacd", p = "abc",通过滑动窗口的执行过程如下:

滑动窗口执行过程图解:
IterationLeftRight窗口内字母频次窗口大小当前窗口字母是否为异位词异位词起始索引
100[c]1c-
201[c, b]2cb-
302[c, b, a]3cba0
413[b, a, e]3bae-
524[a, e, b]3aeb-
635[e, b, a]3eba-
746[b, a, d]3bad-
857[a, b, a]3aba-
968[b, a, c]3bac6
1079[a, c, d]3acd-

详细说明:
  1. Iteration 1-3Right=0Right=2,窗口内包含 [c, b, a],它与 p="abc" 完全匹配,属于异位词,记录起始索引 0

  2. Iteration 4Right=3,窗口内包含 [b, a, e],字母 e 不在 p 中,因此当前窗口不是异位词。

  3. Iteration 5Right=4,窗口内包含 [a, e, b],依旧不匹配 p,当前窗口不是异位词。

  4. Iteration 6Right=5,窗口内包含 [e, b, a],仍然不匹配 p,当前窗口不是异位词。

  5. Iteration 7Right=6,窗口内包含 [b, a, d]d 不在 p 中,因此当前窗口不是异位词。

  6. Iteration 8Right=7,窗口内包含 [a, b, a],当前窗口不是异位词。

  7. Iteration 9Right=8,窗口内包含 [b, a, c],这再次是 p="abc" 的排列,属于异位词,记录起始索引 6

  8. Iteration 10Right=9,窗口内包含 [a, c, d]d 不在 p 中,因此当前窗口不是异位词。


2.3 串联所有单词的子串

题目链接:30. 串联所有单词的子串

题目描述

给定一个字符串 s 和一个字符串数组 wordswords 中所有字符串的长度相同。s 中的 串联子串 是指包含 words 中所有字符串以任意顺序排列连接起来的子串。

例如,如果 words = ["ab","cd","ef"],那么 "abcdef", "abefcd", "cdabef", "cdefab", "efabcd""efcdab" 都是串联子串,而 "acdbef" 不是串联子串,因为它不是 words 排列的连接。

返回所有串联子串在 s 中的开始索引,顺序可以不考虑。

示例 1

  • 输入:s = "barfoothefoobarman", words = ["foo","bar"]
  • 输出:[0,9]
  • 解释:
    子串 "barfoo" 的起始索引为 0,它是 words 中按顺序排列的连接。
    子串 "foobar" 的起始索引为 9,它是 words 中按顺序排列的连接。

示例 2

  • 输入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
  • 输出:[]
  • 解释:
    字符串中没有符合要求的串联子串。

示例 3

  • 输入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]
  • 输出:[6,9,12]
  • 解释:
    子串 "foobarthe" 的起始索引为 6,它是 words 中按顺序排列的连接。
    子串 "barthefoo" 的起始索引为 9,子串 "thefoobar" 的起始索引为 12

提示

  • 1 <= s.length <= 10^4
  • 1 <= words.length <= 5000
  • 1 <= words[i].length <= 30
  • words[i]s 仅包含小写英文字母。

解法:滑动窗口+哈希表

算法思路

本题可以类比为寻找字符串中所有字母异位词的变种问题。不同的是,这里处理的对象是单词而不是单个字符。我们需要遍历字符串 s,并通过滑动窗口找到所有符合条件的单词排列。

在这里插入图片描述

具体步骤:

  1. 使用哈希表 hash1 记录 words 中每个单词的频次。
  2. 遍历字符串 s,每次滑动窗口的大小为 words 中单词的总长度。
  3. 在每个窗口内,维护另一个哈希表 hash2,用于记录当前窗口内单词的频次。
  4. 当两个哈希表的内容一致时,说明当前窗口是一个符合要求的串联子串,记录其起始索引。
    同理,这里比较两个哈希表是否相等时间复杂度也很高,所以我们还是采用优化方式,使用count变量来统计有效字符串的个数即可

算法流程

  1. 初始化 hash1,用于存储 words 中单词的频次。
  2. 遍历 s,通过滑动窗口按单词长度为步长,维护窗口内单词的频次。
  3. 当窗口内的单词频次与 words 中的单词频次一致时,记录该窗口的起始索引。

代码实现

#include <unordered_map>
#include <vector>
#include <string>
using namespace std;class Solution {
public:vector<int> findSubstring(string s, vector<string>& words) {vector<int> ret;unordered_map<string, int> hash1;  // 保存 words 中所有单词的频次for (auto& word : words) hash1[word]++;int len = words[0].size(), m = words.size();for (int i = 0; i < len; i++) {  // 执行 len 次unordered_map<string, int> hash2;  // 维护窗口内单词的频次for (int left = i, right = i, count = 0; right + len <= s.size(); right += len) {string in = s.substr(right, len);  // 进窗口hash2[in]++;if (hash1.count(in) && hash2[in] <= hash1[in]) count++;// 判断是否需要缩小窗口if (right - left + 1 > len * m) {string out = s.substr(left, len);  // 出窗口if (hash1.count(out) && hash2[out] <= hash1[out]) count--;hash2[out]--;left += len;}// 更新结果if (count == m) ret.push_back(left);}}return ret;}
};

复杂度分析:
  • 时间复杂度O(n * m * l),其中 n 是字符串 s 的长度,mwords 中单词的个数,l 是单词的长度。每个单词被扫描一次,并且最多执行 len 次完整的窗口扫描。
  • 空间复杂度O(m * l),用于存储 words 中单词的哈希表以及滑动窗口中的哈希表。

图解分析:
滑动窗口执行过程图解:

假设输入为 s = "barfoothefoobarman", words = ["foo", "bar"],通过滑动窗口的执行过程如下:

具体过程和上一道题类似,核心没变,操作对象从单个字符变成字符串而已,以及一些细节的处理,其他都没啥了,这里就不详细分析了

IterationLeftRight窗口内单词窗口大小当前窗口单词是否为串联子串串联子串起始索引
100[bar]1bar-
203[bar, foo]2barfoo0
369[foo, bar]2foobar9

详细说明:
  1. Iteration 1:窗口内的单词为 [bar],不构成完整的串联子串。
  2. Iteration 2:窗口扩大,内含 [bar, foo],它是 words 中单词的排列,记录起始索引 0
  3. Iteration 3:窗口滑动,内含 [foo, bar],它是 words 中单词的排列,记录起始索引 9

2.4 最小覆盖子串

题目链接:76. 最小覆盖子串

题目描述

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

注意:

  • 对于 t 中重复的字符,最小子串中该字符数量必须不少于 t 中的字符数量。
  • 如果存在这样的子串,答案是唯一的。

示例 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 中只有一个 ‘a’,因此不存在符合条件的子串。

提示

  • 1 <= s.length, t.length <= 10^4
  • st 由英文字母组成。

解法:滑动窗口 + 哈希表

算法思路

这是一个典型的滑动窗口问题。目标是找到字符串 s 中能够覆盖 t 所有字符的最小子串。解决思路如下:

  1. 滑动窗口的应用

    • 我们使用两个哈希表,一个用来记录 t 中每个字符的频次,另一个用来动态维护滑动窗口中的字符频次。
    • 当窗口内的字符满足 t 中每个字符的频次要求时,窗口就是一个可行的解。
  2. 动态调整窗口大小

    • 通过不断扩大窗口右边界,将字符加入窗口。
    • 一旦窗口内的字符满足 t 的要求,开始缩小窗口左边界,尽量缩短窗口长度。

算法流程

  1. 初始化两个哈希表,hash1 用来记录 t 中每个字符的频次,hash2 用来记录窗口内的字符频次。
  2. 使用滑动窗口,右指针 right 不断向右扩展窗口,同时更新窗口内的字符频次。
  3. 每当窗口内的字符频次满足 t 中的要求,开始收缩左指针 left,缩小窗口并更新最小子串的长度。
  4. 当遍历结束后,返回最小子串的起始索引和长度。

这里面还是需要判断两个哈希表是否相等,我们这里还是采用的优化方式,使用count变量来统计有效字符,不过之前两道题是为了统计字符出现的频次,这道题我们统计的是字符出现的种类,所以count++--的情况有所变化喔


代码实现

#include <string>
#include <climits>
using namespace std;class Solution {
public:string minWindow(string s, string t) {int hash1[128] = { 0 }; // 记录字符串 t 中每个字符的频次int kinds = 0;          // 统计 t 中不同的字符种类for (auto ch : t) {if (hash1[ch]++ == 0) kinds++;}int hash2[128] = { 0 }; // 记录窗口中每个字符的频次int minlen = INT_MAX, begin = -1; // 初始化最小长度和起始位置for (int left = 0, right = 0, count = 0; right < s.size(); right++) {char in = s[right];if (++hash2[in] == hash1[in]) count++;  // 进窗口 + 维护 count// 如果当前窗口满足条件,尝试收缩窗口while (count == kinds) {if (right - left + 1 < minlen) {    // 更新最小长度和起始位置minlen = right - left + 1;begin = left;}char out = s[left++];               // 收缩窗口if (hash2[out]-- == hash1[out]) count--;  // 出窗口 + 维护 count}}// 返回结果if (begin == -1) return "";else return s.substr(begin, minlen);}
};

复杂度分析:
  • 时间复杂度O(n),其中 n 是字符串 s 的长度,滑动窗口遍历每个字符最多两次。
  • 空间复杂度O(1),哈希表的大小固定为 128,存储字符频次。

图解分析:

假设输入为 s = "ADOBECODEBANC", t = "ABC",滑动窗口的执行过程如下:

滑动窗口执行过程图解:
IterationLeftRight窗口内字符窗口大小是否为有效窗口最小子串
100[A]1-
201[A, D]2-
302[A, D, O]3-
403[A, D, O, B]4-
504[A, D, O, B, E]5-
605[A, D, O, B, E, C]6ADOBEC
716[D, O, B, E, C, O]6ADOBEC
817[D, O, B, E, C, O, D]7ADOBEC
918[D, O, B, E, C, O, D, E]8ADOBEC
1019[D, O, B, E, C, O, D, E, B]9ADOBEC
11110[D, O, B, E, C, O, D, E, B, A]10ADOBEC
12510[C, O, D, E, B, A]6ADOBEC
13610[O, D, E, B, A]5ADOBEC
14611[O, D, E, B, A, N]6ADOBEC
15612[O, D, E, B, A, N, C]7ADOBEC
16912[B, A, N, C]4BANC

详细说明:
  1. Iteration 1-5:滑动窗口从 Left=0 开始向右扩展,但字符尚未覆盖 t="ABC" 的所有字符,因此没有有效窗口。
  2. Iteration 6Right=5 时,窗口内字符为 [A, D, O, B, E, C],此时首次找到覆盖 t 的有效窗口,记录最小子串为 "ADOBEC"
  3. Iteration 7-10:随着窗口向右扩展,字符无法继续满足 t 的要求,最小子串保持为 "ADOBEC"
  4. Iteration 11Right=10 时,窗口内字符为 [D, O, B, E, C, O, D, E, B, A],再次满足条件,最小子串仍保持为 "ADOBEC"
  5. Iteration 12:窗口左移到 Left=5,依然保持有效窗口,字符为 [C, O, D, E, B, A],最小子串保持不变。
  6. Iteration 16Right=12 时,窗口内字符为 [B, A, N, C],再次找到有效窗口,更新最小子串为 "BANC"

写在最后

在这篇博客中,我们继续探索了滑动窗口的高级应用,通过对一系列复杂问题的深度剖析,进一步展示了滑动窗口的灵活性与高效性。无论是「水果成篮」的双种类约束,还是「找到字符串中所有字母异位词」的字符频次比较,抑或是「串联所有单词的子串」的字符串匹配与「最小覆盖子串」的字符覆盖问题,这些问题都通过滑动窗口的精妙操作得到了优雅的解决。滑动窗口的核心在于对窗口边界的动态调整和哈希表的巧妙使用,结合不同场景的需求,展现了它在复杂算法挑战中的无限可能性。我们不仅解决了实际问题,更深入理解了滑动窗口的算法思想和设计精髓,为后续的算法学习打下了坚实基础。


以上就是关于【优选算法篇】踏入算法的深邃乐章:滑动窗口的极致探秘的内容啦,各位大佬有什么问题欢迎在评论区指正,或者私信我也是可以的啦,您的支持是我创作的最大动力!❤️

在这里插入图片描述

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

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

相关文章

ARM嵌入式学习--第三天

ARM常用伪指令分析 ARM伪指令&#xff1a;为了方便程序员使用&#xff0c;编译器设计的指令&#xff0c;这个指令ARM核无法识别&#xff0c;需要编译器对它翻译成ARM核所识别的指令 -LDR R1&#xff0c;0xabcdef分析 总结&#xff1a; 编译器在编译的时候&#xff0c;将ldr r…

深入拆解TomcatJetty(一)

深入拆解Tomcat&Jetty&#xff08;一&#xff09; 专栏地址&#xff1a;https://time.geekbang.org/column/intro/100027701 1、Web容器是什么 早期的 Web 应用主要用于浏览新闻等静态页面&#xff0c;HTTP 服务器&#xff08;比如 Apache、Nginx&#xff09;向浏览器返…

008、相交链表

0、题目描述 相交链表 1、法1 嵌套循环&#xff0c;从listA的第一个节点开始与listB的每个节点比对&#xff0c;有相同的就返回这个节点。 时间复杂度是n^2 struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {struct ListNode* pa …

多媒体(1)

多媒体 多媒体的信息结构是【非线性的网状结构】 多媒体技术的基本特征&#xff1a;集成性、交互性、实时性、数字化、多样性 多媒体数据具有【数据量大】、【数据类型多】、【数据类型间区别小】、【输入输 出复杂】的特点 在多媒体数据库中&#xff0c;基于内容检索的关键技术…

智联云采 SRM2.0 testService SQL注入漏洞复现

0x01 产品简介 智联云采是一款针对企业供应链管理难题及智能化转型升级需求而设计的解决方案,针对企业供应链管理难题,及智能化转型升级需求,智联云采依托人工智能、物联网、大数据、云等技术,通过软硬件系统化方案,帮助企业实现供应商关系管理和采购线上化、移动化、智能…

【AI绘画】Midjourney进阶:引导线构图详解

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AI绘画 | Midjourney 文章目录 &#x1f4af;前言&#x1f4af;什么是构图为什么Midjourney要使用构图 &#x1f4af;引导线构图特点使用场景提示词书写技巧测试 &#x1f4af;小结 &#x1f4af;前言 【AI绘画】Midjourney进阶&a…

嵌入式职业规划

嵌入式职业规划 在嵌入式的软件开发中&#xff0c;可以分为&#xff1a; 嵌入式MCU软件开发工程师&#xff1b; 嵌入式Linux底层&#xff08;BSP&#xff09;软件开发工程师&#xff1b; 嵌入式Linux应用开发工程师&#xff1b; 嵌入式FPGA算法开发工程师 对于前两个阶段 …

【时间之外】IT人求职和创业应知【9】

目录 1. 云计算ETF领涨,中证云计算与大数据主题指数估值较低 2. 南向资金持有海螺创业市值减少,但仍保持高比例持股 3. 深创赛澳大利亚分站赛落幕,龙岗区与3个意向落地项目签约 认知决定你的赚钱能力。以下是今天可能影响你求职和创业的热点新闻: 今日关键字:数字战争…

ChatGPT官方自带的测试页面 Playground

Playground页面相当于是网页端的大模型调用应用&#xff0c;可以在这里直接选择不同类型模型、选择不同的参数、输入不同的提示测试模型输出结果&#xff0c;并且这个页面还可以查看网页端操作对应的代码&#xff0c;整体操作流程非常便捷&#xff0c;也非常适合初学者进行零代…

UE5 猎户座漂浮小岛 02 模型 地形

UE5 猎户座漂浮小岛 02 模型 地形 1.模型 1.1 导入 1.2 统一模型比例 1.3 添加碰撞体 2.地形 2.1 地 2.2 山体 2.3 海洋 2.4 花草

关于武汉芯景科技有限公司的限流开关芯片XJ6288开发指南(兼容SY6288)

一、芯片引脚介绍 1.芯片引脚 二、系统结构图 三、功能描述 1.EN引脚控制IN和OUT引脚的通断 2.OCB引脚指示状态 3.过流自动断开

Java基于SSM框架的教学辅助微信小程序【附源码、文档】

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

构建后端为etcd的CoreDNS的容器集群(六)、编写自动维护域名记录的代码脚本

本文为系列测试文章&#xff0c;拟基于自签名证书认证的etcd容器来构建coredns域名解析系统。 一、前置文章 构建后端为etcd的CoreDNS的容器集群&#xff08;一&#xff09;、生成自签名证书 构建后端为etcd的CoreDNS的容器集群&#xff08;二&#xff09;、下载最新的etcd容…

hdfs的客户端(big data tools插件)

1.下载hadoop的压缩包在Windows,后解压 2.下载hadoop.dll文件和winutil.exe文件(网上自行查找) 下载完把这两个文件放入hadoop的bin目录 3.设置环境变量: $HADOOP_HOME指向hadoop的文件夹 4.在jetbrains公司的软件里下载big data tools插件:(在此展示的idea的) 下载完重启ide…

1.ubuntu下安装noetic

1.首先安装常规手段安装乌班图系统 2.开始ROS 系统安装 1. 设置编码 $ sudo apt update && sudo apt install locales $ sudo locale-gen en_US en_US.UTF-8 $ sudo update-locale LC_ALLen_US.UTF-8 LANGen_US.UTF-8 $ export LANGen_US.UTF-82.添加源 $ sudo ap…

OpenMediaVault安装插件以及重置web控制台密码

常用插件&#xff08;可根据实际情况选择安装&#xff09; openmediavault-flashmemory&#xff1a;加载临时文件到内存&#xff0c;保护硬盘&#xff1b;openmediavault-fail2ban &#xff1a;扫描日志文件并禁止显示恶意迹象的IP-太多的密码错误&#xff0c;寻找漏洞等&…

【YOLOv11】制作使用YOLOv11的docker环境

目录 一 安装docker 1 安装依赖 2 添加docker官网 GPG 密钥、设置stable 仓库 3 安装 4 使用 二 环境制作 ① 拉基础镜像 ② 起容器 ③ 安装Anaconda3 ④ 安装YOLO11 ⑤ /root/.bashrc ⑥ 退出容器 ⑦ 保存镜像 ⑧ 镜像的使用 一 安装docker ubuntu:20.04 1 安装…

C语言复习第4章 数组

目录 一、一维数组的创建和初始化1.1数组的创建1.2 变长数组1.3 数组的初始化1.4 全局数组默认初始化为01.5 区分两种字符数组1.6 用sizeof计算数组元素个数1.7 如何访问数组元素1.8 一维数组在内存中的存储(连续存储)1.9 访问数组元素的另一种方式:指针变量1.10 数组越界是运行…

手机淘宝自动下单退货自动化RPA脚本机器人

使用手机集线器连接多个手机并发运行。 脚本分3个部分&#xff08;读取本地连接下单&#xff0c;退货获取退货地址信息&#xff0c;填写快递单号&#xff09; 脚本部分图结构看下面的图片 部分数据统计展示

MATLAB支持的字体

listfonts 列出可用的系统字体 {Adobe Devanagari } {Agency FB } {Algerian } {AlienCaret } {AMS } {Arial } {Arial Black …