雙指針算法介紹+算法練習(2025)

?

一、介紹雙指針算法

????????雙指針(或稱為雙索引)算法是一種高效的算法技巧,常用于處理數組或鏈表等線性數據結構。它通過使用兩個指針來遍歷數據,從而減少時間復雜度,避免使用嵌套循環。雙指針算法在解決諸如查找、排序、去重等問題時非常有效。

1.雙指針算法的基本思想

????????雙指針算法的核心思想是通過兩個指針(通常是索引)來遍歷數組或鏈表,而不是使用嵌套循環。這兩個指針可以是:

  • 快慢指針:一個指針移動速度比另一個快。

  • 左右指針:兩個指針從數組的兩端向中間移動。

  • 前后指針:兩個指針從同一個方向移動,但速度或條件不同。

2.常見的雙指針應用場景

1.?快慢指針

快慢指針常用于檢測環、找到鏈表的中間節點等。

示例:檢測鏈表中是否有環

#include <iostream>
using namespace std;struct ListNode {int val;ListNode* next;ListNode(int x) : val(x), next(nullptr) {}
};bool hasCycle(ListNode* head) {ListNode* slow = head;ListNode* fast = head;while (fast != nullptr && fast->next != nullptr) {slow = slow->next;fast = fast->next->next;if (slow == fast) {return true; // 發現環}}return false; // 沒有環
}
2.?左右指針

左右指針常用于數組的兩端向中間遍歷,例如在排序數組中查找兩個數的和。

示例:兩數之和等于目標值

#include <iostream>
#include <vector>
using namespace std;vector<int> twoSum(vector<int>& nums, int target) {int left = 0, right = nums.size() - 1;while (left < right) {int sum = nums[left] + nums[right];if (sum == target) {return {left, right};} else if (sum < target) {left++;} else {right--;}}return {};
}
3.?前后指針

前后指針常用于處理滑動窗口問題或數組中的去重問題。

示例:移除重復項

#include <iostream>
#include <vector>
using namespace std;int removeDuplicates(vector<int>& nums) {if (nums.empty()) return 0;int i = 0; // 前指針for (int j = 1; j < nums.size(); ++j) { // 后指針if (nums[j] != nums[i]) {i++;nums[i] = nums[j];}}return i + 1; // 返回新數組的長度
}

3.雙指針算法的優點

  1. 時間復雜度低:通常可以將時間復雜度從 O(n2) 降低到 O(n)。

  2. 空間復雜度低:不需要額外的存儲空間,通常為 O(1)。

  3. 邏輯清晰:代碼簡潔,易于理解和實現。

4.雙指針算法的局限性

  1. 適用范圍有限:主要用于線性數據結構,如數組和鏈表。

  2. 需要預排序:某些問題(如兩數之和)需要先對數組進行排序。

5.總結

????????雙指針算法是一種非常實用的技巧,適用于多種問題場景。通過合理使用雙指針,可以顯著提高算法的效率,減少不必要的計算。在實際應用中,需要根據具體問題選擇合適的指針策略(如快慢指針、左右指針等)。

二、實戰——題目練習

例一(前后指針)61. 最長不含重復字符的子字符串 - AcWing題庫??????

問題描述

請從字符串中找出一個最長的不包含重復字符的子字符串,計算該最長子字符串的長度。

假設字符串中只包含從?a?到?z?的字符。

數據范圍

輸入字符串長度 [0,1000]。

樣例

輸入:"abcabc"輸出:3

?思路:

使用雙指針算法,根據觀察發現,當使用i,j兩個快慢指針表示當前的指針移動到i的最長不重復序列時候,具有單調性,即i向后移動,j必然向右或者不動,不可能向左移動,這一單調性質導致可以使用雙指針算法。

當快指針所指元素在兩指針區間中重復,則慢指針向右移動,直到快指針所指元素在兩指針區間不充復。?每移動一次計算一下不重復字串的長度,并與已有長度比較取最大值.

🌟 滑動窗口法:最長無重復子串的奇妙冒險 🌟

#include <iostream>
#include <string>
#include <algorithm> 
using namespace std;class Solution {
public:int longest(string str) {int st[26] = {0}; // 📖 字符賬本:記錄26個字母的出現次數(假設只有小寫字母)int res = 0;      // 🏆 冠軍記錄:存儲當前找到的最長子串長度int j = 0;        // 🚪 左門衛:維護窗口左邊界// 🚀 右門衛i的探險之旅:逐個檢查字符串中的字符for (int i = 0; i < str.size(); i++) {// 📌 步驟1:新字符進賬本(比如讀到'a',st[0]加1)st[str[i] - 'a']++;// 🚧 步驟2:發現重復!左門衛開始清理門戶// 當新字符導致重復(賬本中該字符數量>1)while (j < i && st[str[i] - 'a'] > 1) {st[str[j] - 'a']--; // 🧹 左門衛掃過的字符從賬本擦除j++;                 // 🚶♂? 左門衛右移一步}// 📏 步驟3:測量當前窗口長度,刷新冠軍記錄res = max(res, i - j + 1); // ? 比如i=2,j=0時長度是3}return res; // 🏁 返回最終找到的最長長度}
};int main() {Solution ans;string str;cin >> str; int result = ans.longest(str);cout << result << endl; return 0;
}

🎮 生動比喻:貪吃蛇版滑動窗口

想象你控制著一條貪吃蛇在字符串上爬行:

  • 蛇頭(右指針i):不斷向前吞噬字符

  • 蛇尾(左指針j):當吃到重復字符時,蛇尾會收縮直到吐出重復的字符

  • 蛇身:當前窗口內的字符就是蛇的身體

  • 限制規則:蛇的身體不能有重復的字符部件

示例過程:字符串?"abca"

  1. 🐍 蛇吃下 a → 長度1

  2. 🐍 蛇吃下 b → 長度2

  3. 🐍 蛇吃下 c → 長度3

  4. 🐍 蛇吃下 a → 檢測到重復!

    • 蛇尾開始收縮:吐出第一個a → 長度變為3(bca)


🧠 核心原理詳解

步驟操作作用時間復雜度
1??右指針擴張探索新字符,擴大窗口右邊界O(n)
2??檢測重復并收縮左邊界確保窗口內字符唯一總計O(n)
3??實時更新最大長度記錄歷史最大值O(1)

時空復雜度

  • ??時間:左右指針各遍歷一次字符串 → O(2n) ≈?O(n)

  • 💾?空間:固定長度的字符計數器 →?O(1)


🌰 舉個栗子:處理 "abcabcbb"

右指針i當前字符窗口區間操作當前長度最大長度
0a[0,0]記錄a11
1b[0,1]記錄b22
2c[0,2]記錄c33
3a[0,3]發現a重復,收縮窗口到[1,3]33
..................

最終找到最長無重復子串長度為3("abc"或"bca")


🚨 注意事項

  1. 字符范圍:代碼假設輸入為小寫字母,若需支持更多字符需擴大數組大小

  2. 邊界情況:完美處理空字符串(返回0)、全相同字符等情況

  3. 移動邏輯:左指針的移動是跳躍式的,而非逐步移動,確保高效性

這個算法就像兩個默契的探險隊員,一個開拓疆土,一個鞏固后方,共同找到最長的純凈領地! 🏔?

例二(前后指針)

問題描述

給定一個長度為 n 的整數序列,請找出最長的不包含重復的數的連續區間,輸出它的長度。

輸入格式

第一行包含整數 n。

第二行包含 n 個整數(均在 0~1e5 范圍內),表示整數序列。

輸出格式

共一行,包含一個整數,表示最長的不包含重復的數的連續區間的長度。

數據范圍

1≤n≤1e5

樣例輸入

5
1 2 2 3 5

樣例輸出

3

🎪 超市排隊買水果模型 —— 滑動窗口原理詳解

🌟 代碼原理(生動比喻版)

想象你正在超市排隊買水果,規則是:必須選擇連續的一籃水果,且每種水果只能出現一次。你需要找到最長的合格水果籃長度。

角色分配

  1. 收銀員小姐姐 (指針i):不斷掃描新水果放入購物籃右端

  2. 理貨員小哥 (指針j):當發現重復水果時,從購物籃左端拿出水果

  3. 智能標簽 (mid數組):實時統計每種水果在購物籃中的數量

工作流程

  1. 收銀員每拿到一個新水果(i右移),就在標簽上+1

  2. 當發現某個水果數量>1(重復),理貨員開始從左邊拿出水果(j右移),直到重復水果被拿出

  3. 每次操作后測量購物籃長度,記錄歷史最大值


🧩 代碼逐行解析(帶詳細注釋)

#include<bits/stdc++.h>
using namespace std;
const int N =100010;  // 最大水果種類數(假設水果編號不超過10萬)
int arr[N], mid[N], n; // arr-水果隊列,mid-水果計數表,n-總水果數class Solution{
public:int longest(){int res = 0; // 記錄最長無重復水果籃長度// 🛒 開始掃描水果隊列(i是右邊界,j是左邊界)for(int i=0, j=0; i<n; i++) {mid[arr[i]]++; // 🏷? 將新水果加入計數表(比如蘋果+1)// 🚨 發現重復!開始調整左邊界(類似超市警報響起)while(j<i && mid[arr[i]] > 1) {mid[arr[j]]--; // 🧹 把最左邊的水果拿出籃子j++;           // 📏 左邊界右移(購物籃縮短)}// 📐 計算當前購物籃長度,更新最大值res = max(res, i-j+1); }return res; // 🏆 返回最終找到的最大長度}
}; int main()
{Solution ans;cin >> n; // 輸入總水果數// 🍎 輸入水果隊列(比如:蘋果2 香蕉3 蘋果2 橙子4)for(int i=0; i<n; i++) cin >> arr[i]; int end = ans.longest(); // 🧮 計算最長無重復區段cout << end << endl;     // 📢 輸出結果return 0;
}

🌰 舉個栗子:處理序列 [2,3,2,4]

步驟當前水果購物籃內容操作當前長度最大長度
12[2]正常放入11
23[2,3]正常放入22
32[2,3,2]發現重復!--
?? 拿出左邊第一個2[3,2]2
44[3,2,4]正常放入33

最終結果:3(對應子序列 [3,2,4])


🚨 注意事項(常見疑問解答)

  1. 為什么用while不用if

    • 就像超市可能連續拿出多個水果才能消除重復,比如序列 [1,2,1,1] 需要移動j兩次

  2. 數組越界問題

    • 代碼假設水果編號在0-10萬之間,實際使用應根據題目要求調整mid數組大小

  3. 時間復雜度

    • 左右指針各掃描一次,時間復雜度 O(n),比暴力法 O(n2) 高效得多

  4. 空數組處理

    • 當n=0時,返回0,符合邏輯


這個算法就像兩個默契的超市員工,一個不斷擴展貨架,一個及時整理貨物,共同找到最完美的商品陳列方案! 🛒?

例三(左右指針)

1. 題目描述
給定兩個升序排序的有序數組 A 和 B,以及一個目標值 x。

數組下標從 0 開始。請你求出滿足 A[i]+B[j]=x 的數對 (i,j)。

數據保證有唯一解。

輸入格式
第一行包含三個整數 n,m,x,分別表示 A 的長度,B 的長度以及目標值 x。

第二行包含 n 個整數,表示數組 A。

第三行包含 m 個整數,表示數組 B。

輸出格式
共一行,包含兩個整數 i 和 j。

數據范圍
數組長度不超過 1e5。
同一數組內元素各不相同。
1≤數組元素≤1e9

輸入樣例

4 5 6

1 2 4 7
3 4 6 8 9

輸出樣例

1 1

代碼展示?

#include<bits/stdc++.h>
using namespace std;const int N = 100010; // 定義常量N,用于數組的最大長度
int a[N], b[N]; // 定義兩個數組a和b
int n, m, target; // 定義變量n表示數組a的長度,m表示數組b的長度,target表示目標值class Solution {
public:vector<int> targetsum() {for (int i = 0, j = m - 1; i < n; i++) { // 初始化i指向數組a的第一個元素,j指向數組b的最后一個元素while (j >= 0 && a[i] + b[j] > target) { // 如果a[i] + b[j]大于目標值,說明b[j]過大,需要減小jj--;}if (a[i] + b[j] == target) return {i, j}; // 如果找到符合條件的數對,返回索引對(i, j)}return {}; // 根據題意,這里不會執行,因為保證有唯一解}
};int main() {Solution ans; // 創建Solution類的對象anscin >> n >> m >> target; // 輸入數組a的長度n,數組b的長度m,以及目標值targetfor (int i = 0; i < n; i++) cin >> a[i]; // 輸入數組a的所有元素for (int i = 0; i < m; i++) cin >> b[i]; // 輸入數組b的所有元素vector<int> end = ans.targetsum(); // 調用targetsum函數,得到結果cout << end[0] << " " << end[1] << endl; // 輸出結果中的索引對return 0;
}

這段代碼使用雙指針技巧高效地尋找兩個升序數組中滿足和為給定目標值的元素對。以下是其原理的詳細解釋:

核心思路:

  1. 雙指針策略:設定兩個指針i和j,i從數組A的起始位置開始(i=0),j從數組B的末尾開始(j=m-1)。

  2. 利用有序性:由于數組是升序排列,當i增大時A[i]的值變大,此時為了保持總和接近目標值,必須減小B[j]的值(即j左移)。

  3. 指針移動邏輯

    • 對于每個A[i],不斷左移j直到A[i] + B[j] ≤ 目標值。

    • 若此時和等于目標值,立即返回這對下標。

    • 若和仍小于目標值,則i右移以增大總和。

步驟詳解:

  1. 初始化指針:i指向A的最小元素(頭),j指向B的最大元素(尾)。

  2. 調整j的位置:對于當前A[i],若A[i]+B[j]過大,則不斷左移j,直到找到合適的B[j]使和不超過目標。

  3. 檢查匹配:若找到和正好等于目標值的組合,立即返回結果。

  4. 遞增i:若當前組合不滿足,i右移以嘗試更大的A元素,同時j保持在上次調整后的位置(無需重置)。

算法優勢:

  • 時間復雜度O(n+m):每個元素最多被訪問一次,高效處理大規模數據。

  • 空間復雜度O(1):僅使用固定數量的變量,無需額外存儲。

我們可以將這個問題類比成兩人合作調整天平平衡的場景,幫助理解雙指針的工作原理:


📖 生活場景類比

想象你和小伙伴在實驗室調整一架天平。天平左側的砝碼盒(數組A)按重量從小到大排列,右側的砝碼盒(數組B)按重量從大到小排列。你們需要各選一個砝碼,使得兩側砝碼的總重量剛好等于目標值?x

操作規則:
  1. 你的策略(指針i):從左側砝碼盒最輕的開始(i=0),依次嘗試更重的砝碼。

  2. 小伙伴的策略(指針j):從右側砝碼盒最重的開始(j=m-1),依次嘗試更輕的砝碼。

動態調整過程:
  • 情況1:總和太重
    當你選中左側的砝碼?A[i]?時,小伙伴發現當前右側的砝碼?B[j]?加上你的選擇后總重量超過了目標值?x。此時小伙伴會主動換一個更輕的右側砝碼(j--),直到總重量不再超標。

  • 情況2:總和合適
    如果調整后的?A[i] + B[j]?正好等于?x,兩人立刻停止,成功找到解!

  • 情況3:總和太輕
    如果調整到最輕的右側砝碼后,總重量仍不足,你會換一個更重的左側砝碼(i++),而小伙伴保持當前右側砝碼的位置繼續配合。


🌟 類比與代碼的映射

生活場景代碼邏輯意義
左側砝碼盒(從小到大排列)數組?A?升序排列指針?i?從左向右移動,嘗試更大的值
右側砝碼盒(從大到小排列)數組?B?升序排列,但指針?j?從右向左移動指針?j?從右向左移動,嘗試更小的值
兩人實時溝通調整策略雙指針?i?和?j?協同移動通過反向移動縮小搜索范圍
找到平衡點后停止返回?{i, j}確保唯一解被高效定位

📝 代碼注釋與生活場景結合

vector<int> targetsum() {for (int i = 0, j = m - 1; i < n; i++) {  // 你從最輕的左側砝碼開始嘗試while (j >= 0 && a[i] + b[j] > target) { j--;  // 小伙伴不斷換更輕的右側砝碼,直到總重量不超標}if (a[i] + b[j] == target) {  // 天平平衡,找到解!return {i, j};}// 若總和太輕,你主動換下一個更重的砝碼(i++),小伙伴保持當前位置}
}

💡 為什么這個策略高效?

  • 避免重復嘗試:一旦小伙伴調整到某個右側砝碼?B[j],后續你更換更重的左側砝碼時,小伙伴只需從上一次的位置繼續向左調整,無需從頭開始(時間復雜度僅為?O(n + m))。

  • 利用有序性:砝碼盒的排列順序(升序/降序)天然引導指針移動方向,類似“夾逼”逐漸逼近目標。


這個類比將抽象的算法轉化為具體的合作場景,生動展現了雙指針如何通過“一增一減”的協同策略高效解決問題。

例四

【acwing 2816. 判斷子序列】

問題描述

給定一個長度為 n 的整數序列 a1,a2,…,a_{n} 以及一個長度為 m 的整數序列 b1,b2,…,b_{m}

請你判斷 a 序列是否為 b 序列的子序列。

子序列指序列的一部分項按原有次序排列而得的序列,例如序列 {a1,a3,a5} 是序列 {a1,a2,a3,a4,a5} 的一個子序列。

輸入格式

第一行包含兩個整數 n,m。

第二行包含 n 個整數,表示 a1,a2,…,an。

第三行包含 m 個整數,表示 b1,b2,…,bm。

輸出格式

如果 a 序列是 b 序列的子序列,輸出一行 Yes。

否則,輸出 No。

數據范圍

1≤n≤m≤1e5
?1e9≤a_{i},b_{i}≤1e9

輸入樣例:

3 5
1 3 5
1 2 3 4 5

輸出樣例:

Yes

#include<iostream>
using namespace std;// 定義常量N為100010,用于限定數組的最大大小
const int N = 100000 + 10;
int a[N], b[N]; // 定義兩個整型數組a和b,用于存儲輸入的數據int main()
{// n表示數組a的長度,m表示數組b的長度int n, m;// 從標準輸入讀取n和m的值scanf("%d%d", &n, &m);// 循環讀入數組a的n個元素for(int i = 0; i < n; i++) scanf("%d",&a[i]);// 循環讀入數組b的m個元素for(int i = 0; i < m; i++) scanf("%d",&b[i]);// 初始化兩個索引i和j分別為0,分別用于遍歷數組a和bint i = 0, j = 0;// 當數組a沒有完全匹配完(i<n)且數組b沒有被完全掃描過(j<m),繼續循環while(i < n && j < m){// 如果當前數組a的元素a[i]與數組b的元素b[j]相等,則說明找到了一個匹配if(a[i] == b[j]){// 移動數組a的指針i到下一個位置,繼續尋找下一個匹配i++;}// 不管是否找到匹配,都需要移動數組b的指針j到下一個位置,繼續掃描j++;}// 如果數組a的所有元素都被成功匹配了(即i==n),則輸出"Yes"if(i == n) puts("Yes");// 否則,如果數組a中有任何元素未被匹配,則輸出"No"else puts("No");return 0;
}

通俗比喻

想象你在玩一個“按順序找字母”的游戲:

  • 你手上有張字母卡?a = [A, B, C],需要在另一張長紙條?b?上按順序找到這些字母,順序不能亂,但中間可以有其他字母。

  • 你從紙條的開頭開始找:

    • 找到?A?后,打勾,繼續往后找?B

    • 如果中途遇到其他字母(比如?X),直接跳過,繼續往后找。

    • 如果紙條找完了還沒找齊所有字母,游戲失敗;否則成功。

這段代碼就是實現這個游戲的過程。

例五、

【acwing 32. 調整數組順序使奇數位于偶數前面】

問題描述

輸入一個整數數組,實現一個函數來調整該數組中數字的順序。 使得所有的奇數位于數組的前半部分,所有的偶數位于數組的后半部分。

樣例

輸入:1 2 3 4 5

輸出:? ?1 3 5 2 4

法一、雙指針算法?

不過需要注意的是,雖然這種方法能確保奇數在前、偶數在后,但它并不保證相同類型元素之間的相對順序不變。

#include <vector>
#include<iostream>
using namespace std;class Solution {
public:// 定義resort函數,用于重新排序數組,使得所有奇數排在前面,偶數排在后面void resort(vector<int>& array) {int i = 0, j = 0; // 初始化兩個指針i和j都指向數組的起始位置// 遍歷整個數組while (j < array.size()) {// 如果array[j]是奇數,則將其與array[i]交換,并增加iif (array[j] % 2 == 1) { // 檢查當前元素是否為奇數swap(array[i], array[j]); // 交換array[i]和array[j]i++; // 移動i指針,指向下一個應該放置奇數的位置}// 無論是否執行了交換操作,都要增加j,繼續檢查下一個元素j++;}}
};int main(){Solution solve; // 創建Solution類的一個實例vector<int> arr; // 定義一個整型向量arr用于存儲輸入數據int mid; // 定義一個變量mid用于臨時存儲從標準輸入讀取的數據// 循環讀取輸入直到文件結束(EOF)while(cin >> mid) {arr.push_back(mid); // 將讀取的值添加到arr向量中}solve.resort(arr); // 調用resort函數對數組進行重新排序// 輸出重新排序后的數組for(int num : arr) {cout << num << " "; // 打印每個元素,后面跟一個空格}return 0; // 程序正常退出
}

?法二、分治+歸并

了解vector的insert用法:介紹C++vector的insert函數用法-CSDN博客

這種方法的優點在于它簡單直接,能夠保證奇數和偶數各自內部的原始順序不變,即實現了穩定的排序。不過,它的缺點是需要額外的空間來存儲奇數和偶數,因此空間復雜度為O(n),n是數組的長度。如果內存限制嚴格,可能需要考慮其他不使用額外空間的方法。

#include <vector>
#include<iostream>
using namespace std;class Solution {
public:// 定義resort函數,用于重新排序數組,使得所有奇數排在前面,偶數排在后面void resort(vector<int>& array) {vector<int> odd, even; // 創建兩個新的向量odd和even,分別用于存儲奇數和偶數// 遍歷整個輸入數組for(int num : array) {if(num % 2 == 1) { // 如果當前數字是奇數odd.push_back(num); // 將其添加到odd向量中} else { // 如果當前數字是偶數even.push_back(num); // 將其添加到even向量中}}// 合并結果:先放奇數,再放偶數odd.insert(odd.end(), even.begin(), even.end()); // 將even向量的所有元素添加到odd向量的末尾array = odd; // 更新原數組為合并后的結果}
};int main(){Solution solve; // 創建Solution類的一個實例vector<int> arr; // 定義一個整型向量arr用于存儲輸入數據int mid; // 定義一個變量mid用于臨時存儲從標準輸入讀取的數據// 循環讀取輸入直到文件結束(EOF)while(cin >> mid) {arr.push_back(mid); // 將讀取的值添加到arr向量中}solve.resort(arr); // 調用resort函數對數組進行重新排序// 輸出重新排序后的數組for(int num : arr) {cout << num << " "; // 打印每個元素,后面跟一個空格}return 0; // 程序正常退出
}

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/72053.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/72053.shtml
英文地址,請注明出處:http://en.pswp.cn/web/72053.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【每日八股】計算機網絡篇(四):HTTP

目錄 HTTP 與 HTTPS 的區別&#xff1f;HTTPS 加密與認證的過程&#xff1f;ClientHelloServerHello客戶端回應服務端回應 HTTPS 一定安全可靠嗎&#xff1f;HTTPS 狀態碼的含義&#xff1f;HTTP 緩存有哪些實現方式&#xff1f;HTTP 1.0、HTTP 1.1、HTTP 2.0 和 HTTP 3.0 的區…

TMS320F28P550SJ9學習筆記10:軟件模擬I2C通信_驅動1.3寸OLED

現在有了具體的I2C通信器件&#xff0c;一塊1.3寸OLED屏幕&#xff0c;今日嘗試移植配置一下: 本文主要講的是&#xff0c;使用軟件模擬I2C通信 文章提供測試代碼講解、完整工程下載、測試效果圖 目錄 前置文章&#xff1a; I2C通信引腳&#xff1a; 軟件I2C 引腳的初始化&am…

spring boot 發送郵件驗證碼

一、前置需求 1、準備郵箱 2、登錄授權碼 qq郵箱在–>設置–>賬號POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服務 開啟服務 二、發送郵件 1、簡單郵件 包含郵件標題、郵件正文 2、引入mail啟動器 <dependency><groupId>org.springframework.boot</groupI…

塔能科技:智能機箱,為城市安防 “智” 造堅實堡壘

在當今智慧城市建設的浪潮中&#xff0c;城市安防面臨著諸多挑戰。設備管理難&#xff0c;眾多分散的安防設備猶如一盤散沙&#xff0c;難以實現高效統一的管控&#xff1b;數據傳輸不穩定&#xff0c;關鍵時刻信息的延遲或丟失&#xff0c;可能導致嚴重后果。這些問題嚴重制約…

電商數據分析 電商平臺銷售數據分析 電商平臺數據庫設計 揭秘電商怎么做數據分析

《電商參謀數據分析平臺方案》&#xff08;28頁PPT&#xff09;是一套為電商行業量身定制的一體化解決方案&#xff0c;它通過全鏈路打通從數據獲取到分析的全過程&#xff0c;幫助電商企業實現精細化運營和市場機會的挖掘。該方案針對電商行業在數據獲取、加工整合及業務賦能方…

uniapp uview 1.0 跨域h5配置多個代理、如何請求接口

參考文章&#xff1a;uniapp uView1.0跨域h5配置多個代理 官方手冊&#xff1a;http 請求 項目中使用&#xff1a; 參考其他博主的文章是在manifest.json中配置代理&#xff0c;但在官方的手冊中是直接在script請求的&#xff0c;我嘗試請求了下沒問題&#xff0c;上線后也不…

MAVEN解決版本依賴沖突

文章目錄 一、依賴沖突概念1、什么是依賴沖突2、依賴沖突的原因3、如何解決依賴沖突 二、查看依賴沖突-maven-helper1、安裝2、helper使用1、conflicts的閱讀順序&#xff08;從下向上看&#xff09;2、dependencies as List的閱讀順序&#xff08;從下向上看&#xff09;3、de…

79.ScottPlot的MVVM實現 C#例子 WPF例子

如何通過數據綁定在 WPF 中實現動態圖像顯示 在 WPF 應用程序中&#xff0c;通過數據綁定實現動態圖像顯示是一種高效且優雅的方式。以下是一個簡單的教程&#xff0c;展示如何使用 ScottPlot.WPF 庫和 MVVM 模式來實現這一功能。 第一步&#xff1a;安裝必要的 NuGet 包 首…

簡單工廠 、工廠方法模式和抽象工廠模式

簡單工廠 、工廠方法模式和抽象工廠模式 1.模式性質與定位 簡單工廠:并非正式的設計模式(屬編程習慣),通過單一工廠類根據參數判斷創建不同產品,本質是將對象創建邏輯集中管理。 工廠方法:是標準的創建型設計模式,定義抽象創建接口,由子類決定實例化哪個具體產品類,…

熱圖回歸(Heatmap Regression)

熱圖回歸(Heatmap Regression)是一種常用于關鍵點估計任務的方法,特別是在人體姿態估計中。它的基本思想是通過生成熱圖來表示某個關鍵點在圖像中出現的概率或強度。以下是熱圖回歸的主要特點和工作原理: 主要特點 熱圖表示: 每個關鍵點對應一個熱圖,熱圖中的每個像素值…

Word 小黑第15套

對應大貓16 修改樣式集 導航 -查找 第一章標題不顯示 再選中文字 點擊標題一 修改標題格式 格式 -段落 -換行和分頁 勾選與下段同頁 添加腳注 &#xff08;腳注默認位于底部 &#xff09;在腳注插入文檔屬性&#xff1a; -插入 -文檔部件 -域 類別選擇文檔信息&#xff0c;域…

Java 大視界 -- Java 大數據在智能安防視頻摘要與檢索技術中的應用(128)

&#x1f496;親愛的朋友們&#xff0c;熱烈歡迎來到 青云交的博客&#xff01;能與諸位在此相逢&#xff0c;我倍感榮幸。在這飛速更迭的時代&#xff0c;我們都渴望一方心靈凈土&#xff0c;而 我的博客 正是這樣溫暖的所在。這里為你呈上趣味與實用兼具的知識&#xff0c;也…

Python里matplotlib不顯示中文的問題

在很長一段時間里用Python繪圖&#xff0c;matplotlib都不能很好的顯示中文&#xff0c;起初是認為我的pycharm里的設置問題&#xff0c;但是發現同樣的問題在spyder里也同樣的出現。 一共有兩種解決方案&#xff0c;我強烈推薦第一種&#xff0c;因為更為方便&#xff0c;繪圖…

JavaWeb-servlet6中request和response的使用

HttpServletRequest HttpServletRequest 繼承自 ServletRequest。客戶端瀏覽器發出的請求被封裝成為一個 HttpServletRequest對象。 對象包含了客戶端請求信息包括請求的地址&#xff0c;請求的參數&#xff0c;提交的數據&#xff0c;上傳的文件客戶端的ip甚至客戶端操作系統…

機器學習(吳恩達)

一, 機器學習 機器學習定義: 計算機能夠在沒有明確的編程情況下學習 特征: 特征是描述樣本的屬性或變量&#xff0c;是模型用來學習和預測的基礎。如: 房屋面積, 地理位置 標簽: 監督學習中需要預測的目標變量&#xff0c;是模型的輸出目標。如: 房屋價格 樣本: 如: {面積100㎡…

CNN的激活函數

我們來對比 Sigmoid、Softmax 和 ReLU 這三種激活函數的相同點和不同點&#xff0c;并分別說明它們相較于其他兩種激活函數的優點。 相同點 都是非線性激活函數&#xff1a; 這三種激活函數都能為神經網絡引入非線性特性&#xff0c;使網絡能夠學習復雜的模式。 廣泛應用于深度…

Oracle數據恢復:閃回查詢

Oracle數據恢復:閃回查詢 SQL語法閃回查詢:AS OF閃回版本查詢:VERSIONS BETWEEN數據恢復示例閃回查詢最佳實踐應用場景使用限制注意事項最佳實踐在誤刪除業務數據時,Oracle數據庫通常支持以下幾種數據恢復途徑。 閃回查詢(Flashback Query):閃回查詢通過查詢系統的UNDO數…

【MySQL篇】MySQL內置函數

目錄 1&#xff0c;日期函數 2&#xff0c;字符串函數 3&#xff0c;數學函數 4&#xff0c;其他函數 實戰OJ 1&#xff0c;日期函數 日期類型在之前文章【數據類型】中有描述 傳送門&#xff1a;【MySQL篇】數據類型_mysql 數據類型-CSDN博客 函數名稱描述current_dat…

蘋果iOS 18.4將強制升級HomeKit架構,舊版設備或無法使用

在科技飛速發展的當下,智能家居領域也在不斷革新。而蘋果公司作為科技行業的巨頭,其每一次動作都備受關注。近日,有消息稱蘋果計劃在iOS 18.4版本中停止對舊版HomeKit架構的支持,這一舉措意味著用戶將被迫升級,也可能對眾多使用Apple Home應用的智能家居設備用戶產生深遠影…

故障診斷——neo4j入門

文章目錄 neo4jQuickStartDemo neo4j QuickStart 詳情可見博客&#xff1a;https://www.cnblogs.com/nhdlb/p/18703804&#xff0c;使用docker拉取最近的一個版本進行創建 docker run -it -d -p 7474:7474 -p 7687:7687 \ -v /disk5/neo4j_docker/data:/data \ -v /disk5/ne…