數據結構——樹(04二叉樹,二叉搜索樹專項,代碼練習)

文章目錄

  • 一、概念
  • 二、構造
    • 1.1先序序列 構造BST
    • 1.2中序序列 轉換為BST
    • 1.3中序序列鏈表轉換為BST
    • 1.4BST轉換為中序序列鏈表
    • 1.7BST的序列化和反序列化
    • 1.6BST的種數
  • 二、BST的增刪改查
    • 2.1驗證是否為BST
    • 2.2查找值為val的節點
    • 2.3插入一個值為val的節點
    • 2.4刪除一個值為val的節點
    • 2.5恢復錯誤的兩節點
    • 2.6修剪BST
    • 2.7平衡化
  • 三、BST的其他問題
    • 3.1第K小的元素
    • 3.2眾數
    • 3.3兩數之和
    • 3.4給定范圍的節點之和
    • 3.5節點最小距離
    • 3.6二叉搜索樹轉換為累加樹
    • 3.7最近結果查詢

一、概念

二叉搜索樹(Binary Search Tree,簡稱 BST)是一種特殊的二叉樹,其核心特性圍繞 “節點值的有序性” 展開。

定義性特征:對于二叉搜索樹中的任意節點,滿足:

  • 左子樹所有節點的值 < 當前節點的值
  • 右子樹所有節點的值 > 當前節點的值
  • 左、右子樹本身也必須是二叉搜索樹(遞歸滿足上述條件)。
  • 標準 BST 中通常不允許存在值相等的節點。
    在這里插入圖片描述

衍生特征:

  • 中序遍歷結果為升序序列,得到的節點值序列是嚴格遞增的。這是 BST 最常用的特性之一,可用于驗證一棵樹是否為 BST,或通過升序序列反向構造 BST。
  • 樹中最小值一定是最左側的葉子節點(一路向左子樹遍歷,直到無左孩子);
    樹中最大值一定是最右側的葉子節點(一路向右子樹遍歷,直到無右孩子)。
  • 查找目標值target的過程類似二分查找:若當前節點值等于target,找到目標;若target小于當前節點值,遞歸查找左子樹;若target大于當前節點值,遞歸查找右子樹。時間復雜度為O(log n),最壞情況(退化為鏈表)為O(n)。
  • 平衡二叉樹是 BST 的進階,通過額外機制保證左右子樹高度差不超過 1,避免了 BST 在極端情況下退化為鏈表。

二、構造

序號題目鏈接
1先序序列構造https://leetcode.cn/problems/construct-binary-search-tree-from-preorder-traversal/description/?envType=problem-list-v2&envId=tree
2中序序列構造https://leetcode.cn/problems/convert-sorted-array-to-binary-search-tree/?envType=problem-list-v2&envId=tree
3中序有序鏈表構造https://leetcode.cn/problems/convert-sorted-list-to-binary-search-tree/?envType=problem-list-v2&envId=tree
4BST轉換為中序有序鏈表https://leetcode.cn/problems/increasing-order-search-tree/description/?envType=problem-list-v2&envId=tree
5BST的序列化和反序列化https://leetcode.cn/problems/serialize-and-deserialize-bst/description/?envType=problem-list-v2&envId=tree
1BST的種數1【總數】https://leetcode.cn/problems/unique-binary-search-trees/description/?envType=problem-list-v2&envId=tree
2BST的種數2【列舉】https://leetcode.cn/problems/unique-binary-search-trees-ii/solutions/339143/bu-tong-de-er-cha-sou-suo-shu-ii-by-leetcode-solut/?envType=problem-list-v2&envId=tree

1.1先序序列 構造BST

先序序列的特點是:根左右。結合BST的特性可知:

  • 序列的第一個元素一定是根節點
  • 根【左(比根小)】【右(比根大)】。根節點后面的元素,只要比第一個元素小的都是BST的左子樹,右子樹同理。
    在這里插入圖片描述
TreeNode* build(vector<int>& pre,int start,int end){//遞歸的出口if (start > end) return nullptr;//根節點int rootVal=pre[start];TreeNode* root=new TreeNode(rootVal);// 找到左子樹與右子樹的分割點(第一個大于根節點值的位置為右子樹的第一個元素)int index;for(index=start+1;index<=end;index++){if(pre[index]>rootVal) break;}//遞歸構造左子樹和右子樹root->left = build(pre, start + 1, index - 1);root->right = build(pre, index, end);return root;
}

1.2中序序列 轉換為BST

與先序序列轉換一樣。中序序列的特點是:左根右。結合BST的性質。

  • 序列的中間元素為樹的根節點。
  • 【左】根【右】。在根節點左邊的為左子樹,根節點右邊的為右子樹(遞歸構造)
TreeNode* build(vector<int>& nums,int start,int end){if(start>end) return nullptr;int mid=(start+end)/2;int rootVal=nums[mid];TreeNode* root=new TreeNode(rootVal);root->left=build(nums,start,mid-1);root->right=build(nums,mid+1,end);return root;
}

1.3中序序列鏈表轉換為BST

有序鏈表轉換成二叉搜索樹的原理同 中序遍歷轉換為二叉樹。

TreeNode* build(ListNode* head,int left,int right){if(left>right) return nullptr;int mid=(left+right)/2;//訪問鏈表在mid處的值 p指向的是根節點ListNode* p=head;for(int i=1;i<=mid;i++){p=p->next;}TreeNode* root=new TreeNode(p->val);//遞歸左右子樹root->left=build(head,left,mid-1);root->right=build(head,mid+1,right);return root;
}

1.4BST轉換為中序序列鏈表

  • 將樹按照中序遍歷,遍歷結果放在res中。為中序序列。
  • 按照res構建鏈表。【next變成right】
void dfs(TreeNode* root, vector<int>& result){if(root==nullptr) return ;dfs(root->left,result);result.push_back(root->val);dfs(root->right,result);
}
TreeNode* increasingBST(TreeNode* root) {vector<int> res;dfs(root,res);TreeNode* dummy=new TreeNode(-1);TreeNode* p=dummy;for(int val:res){p->right=new TreeNode(val);p=p->right;}return dummy->right;
}

1.7BST的序列化和反序列化

  • 序列化:BST先序遍歷——遍歷結果字符串
  • 反序列化:遍歷結果字符串——BST
// 前序遍歷:根->左->右,將節點值拼接為字符串(用逗號分隔)
void preorder(TreeNode* node, string& result) {if (node == nullptr) return;// 拼接當前節點值if (!result.empty()) {result += ",";}result += to_string(node->val);// 遞歸遍歷左右子樹preorder(node->left, result);preorder(node->right, result);
}// 參考【先序序列構造BST】
TreeNode* buildBST(vector<int>& values, int start, int end) {}// Encodes a tree to a single string.
string serialize(TreeNode* root) {string result;preorder(root, result);return result;
}// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {if (data.empty()) return nullptr;// 將字符串分割為整數列表(前序遍歷結果)vector<int> values;stringstream ss(data);string item;while (getline(ss, item, ',')) {values.push_back(stoi(item));}// 根據前序遍歷結果構建BSTreturn buildBST(values, 0, values.size() - 1);
}

1.6BST的種數

  • 對于 i 個節點,我們可以選擇 j(1 ≤ j ≤ i)作為根節點
  • 此時左子樹有 j-1 個節點,右子樹有 i-j 個節點
  • 以 j 為根的二叉搜索樹數量 = 左子樹數量 × 右子樹數量,即 dp[j-1] × dp[i-j]
  • 對所有可能的根節點求和,得到 dp[i]
    在這里插入圖片描述
int numTrees(int n) {vector<int> dp(n+1,0);dp[0]=1;dp[1]=1;for(int i=2;i<=n;i++){for(int j=1;j<=i;j++){dp[i] += dp[j-1] * dp[i-j];}}return dp[n];
}

上述題目是BST有幾種可能,下列代碼是BST的每一種可能都列舉出來。

// 生成[start, end]范圍內所有可能的BST
vector<TreeNode*> generate(int start, int end) {vector<TreeNode*> trees;// 遞歸終止條件:區間為空,返回空節點if (start > end) {trees.push_back(nullptr);return trees;}// 嘗試以每個數作為根節點for (int i = start; i <= end; ++i) {// 生成左右子樹vector<TreeNode*> leftTrees = generate(start, i - 1);vector<TreeNode*> rightTrees = generate(i + 1, end);// 組合左子樹和右子樹,形成以i為根的樹for (TreeNode* left : leftTrees) {for (TreeNode* right : rightTrees) {TreeNode* root = new TreeNode(i);root->left = left;root->right = right;trees.push_back(root);}}}return trees;
}
vector<TreeNode*> generateTrees(int n) {if (n == 0) return {};return generate(1, n);
}

二、BST的增刪改查

序號題目鏈接
1驗證BST是否有效【中序序列】https://leetcode.cn/problems/validate-binary-search-tree/solutions/2020306/qian-xu-zhong-xu-hou-xu-san-chong-fang-f-yxvh/?envType=problem-list-v2&envId=tree
2查找值為val的節點https://leetcode.cn/problems/search-in-a-binary-search-tree/?envType=problem-list-v2&envId=tree
3插入1個節點https://leetcode.cn/problems/insert-into-a-binary-search-tree/description/?envType=problem-list-v2&envId=tree
4刪除1個節點https://leetcode.cn/problems/delete-node-in-a-bst/description/?envType=problem-list-v2&envId=tree
5恢復BSThttps://leetcode.cn/problems/recover-binary-search-tree/description/?envType=problem-list-v2&envId=tree
6修剪BSThttps://leetcode.cn/problems/trim-a-binary-search-tree/description/?envType=problem-list-v2&envId=tree
7平衡化https://leetcode.cn/problems/balance-a-binary-search-tree/description/?envType=problem-list-v2&envId=tree

2.1驗證是否為BST

驗證所給的樹是否為有效的二叉搜索樹

二叉搜索樹的中序遍歷是有序的,且是升序的。【數組 or 遞歸 or 非遞歸】

  • 解法1:將中序遍歷的結果放在數組中。比較【當前節點】與【當前節點的前一個節點】
  • 解法2:pre 記錄中序遍歷序列中 “當前節點的前一個節點”。比較當前節點與 pre 的值。
bool isValidBST(TreeNode* root) {vector<int> inorder;// 中序遍歷inorderTraversal(root, inorder);// 檢查是否嚴格遞增for (int i = 0; i < inorder.size()-1; i++) {// 注意:必須嚴格小于,不能等于if (inorder[i+1] <= inorder[i]) return 0;}return 1;
}
TreeNode* pre=nullptr;
bool isValidBST(TreeNode* root) {if(root==nullptr) return 1;if(isValidBST(root->left)==false)  return 0;  //左if(pre!=nullptr && root->val <= pre->val){    //中return 0;}pre=root;return isValidBST(root->right);              //右
}

2.2查找值為val的節點

二叉樹的特性就是:左小右大。因此想在二叉樹中進行搜索某個值,可以進行比較。

  • 如果val小于當前節點值——左子樹中繼續查找
  • 如果val等于當前節點值——查找成功
  • 如果val大于當前節點值——右子樹中繼續查找
TreeNode* searchBST(TreeNode* root, int val) {if(root==nullptr) return nullptr;if(root->val==val) return root;else if(val<root->val) return searchBST(root->left,val);else if(val>root->val) return searchBST(root->right,val);return nullptr;}

2.3插入一個值為val的節點

BST的性質:遞歸處理左子樹和右子樹

TreeNode* insertIntoBST(TreeNode* root, int val) {if (root == nullptr)  return new TreeNode(val);if (val < root->val)  root->left = insertIntoBST(root->left, val);else  root->right = insertIntoBST(root->right, val);return root;
}

2.4刪除一個值為val的節點

在這里插入圖片描述

TreeNode* deleteNode(TreeNode* root, int key) {if(root==nullptr) return nullptr;// 查找目標節點if(key < root->val) root->left=deleteNode(root->left,key);else if(key > root->val) root->right=deleteNode(root->right,key);else{// 情況1:葉子節點,直接刪除if(root->left==nullptr && root->right==nullptr){delete root;return nullptr;}// 情況2:只有右子樹(修正指針指向)else if(root->left==nullptr){TreeNode* temp=root->right;  delete root;return temp;}// 情況3:只有左子樹(修正指針指向)else if(root->right==nullptr){TreeNode* temp=root->left;  delete root;return temp;}// 情況4:有左右子樹else{// 找到右子樹最小節點TreeNode* minNode=root->right;while(minNode->left!=nullptr){minNode=minNode->left;}// 替換當前節點值root->val=minNode->val;root->right=deleteNode(root->right, minNode->val);}}return root;
}

2.5恢復錯誤的兩節點

給你的根節點 root ,該樹中的 恰好 兩個節點的值被錯誤地交換。請在不改變其結構的情況下,恢復這棵樹 。
在這里插入圖片描述

// 中序遍歷
void inorder(TreeNode* root) {if (root == nullptr) return;inorder(root->left); // 遍歷左子樹if (prev != nullptr && root->val < prev->val) {// 第一次發現逆序對,記錄前一個節點if (first == nullptr) first = prev;// 第二次發現逆序對(或相鄰交換的情況),記錄當前節點second = root;}prev = root;  // 更新前一個節點inorder(root->right); // 遍歷右子樹
}
void recoverTree(TreeNode* root) {inorder(root);swap(first->val, second->val);
}

2.6修剪BST

給你二叉搜索樹的根節點 root ,同時給定最小邊界low 和最大邊界 high。通過修剪二叉搜索樹,使得所有節點的值在[low, high]中。修剪樹 不應該 改變保留在樹中的元素的相對結構 。

  • 若當前節點值 < low:左子樹所有值都 < low,直接用右子樹的修剪結果替換當前節點。
  • 若當前節點值 > high:右子樹所有值都 > high,直接用左子樹的修剪結果替換當前節點。
  • 若當前節點值在范圍內:保留該節點,遞歸修剪其左右子樹并重新連接。
TreeNode* trimBST(TreeNode* root, int low, int high) {if(root==nullptr) return nullptr;if(root->val < low) return trimBST(root->right,low,high);if(root->val > high) return trimBST(root->left,low,high);root->left=trimBST(root->left,low,high);root->right=trimBST(root->right,low,high);return root;
}

2.7平衡化

  • 對原 BST 進行中序遍歷,得到一個有序的節點值序列【參考樹的中序遍歷】
  • 利用有序序列構建平衡 BST—— 通過選擇序列的中間元素作為根節點,左側元素構建左子樹,右側元素構建右子樹,確保左右子樹高度差不超過 1。【參考中序序列構造BST】
// 中序遍歷BST,獲取有序序列
void inorder(TreeNode* node, vector<int>& values) {if (node == nullptr) return;inorder(node->left, values);values.push_back(node->val);inorder(node->right, values);
}
// 從有序數組的[left, right]范圍構建平衡BST
TreeNode* buildBalancedBST(vector<int>& values, int left, int right) {if (left > right) return nullptr;//選擇中間元素作為根節點int mid = left + (right - left) / 2;TreeNode* node = new TreeNode(values[mid]);// 遞歸構建左右子樹node->left = buildBalancedBST(values, left, mid - 1);node->right = buildBalancedBST(values, mid + 1, right);return node;
}
TreeNode* balanceBST(TreeNode* root) {vector<int> values;inorder(root, values);return buildBalancedBST(values, 0, values.size() - 1);
}

三、BST的其他問題

序號題目鏈接
1BST第K小的元素【中序第K元素】https://leetcode.cn/problems/kth-smallest-element-in-a-bst/description/?envType=problem-list-v2&envId=tree
2BST的眾數【哈希表】https://leetcode.cn/problems/find-mode-in-binary-search-tree/description/?envType=problem-list-v2&envId=tree
3BST中的兩數之和是否為targethttps://leetcode.cn/problems/two-sum-iv-input-is-a-bst/description/?envType=problem-list-v2&envId=tree
4BST給定范圍的節點之和https://leetcode.cn/problems/range-sum-of-bst/description/?envType=problem-list-v2&envId=tree
5BST節點最小距離https://leetcode.cn/problems/minimum-distance-between-bst-nodes/description/?envType=problem-list-v2&envId=tree
6BST的最小絕對差【同上】https://leetcode.cn/problems/minimum-absolute-difference-in-bst/description/?envType=problem-list-v2&envId=tree
7二叉搜索樹轉換為累加樹https://leetcode.cn/problems/convert-bst-to-greater-tree/description/?envType=problem-list-v2&envId=tree
8BST的最近公共祖先【同二叉樹】https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/description/?envType=problem-list-v2&envId=tree
9最近節點查詢https://leetcode.cn/problems/closest-nodes-queries-in-a-binary-search-tree/description/?envType=problem-list-v2&envId=tree

3.1第K小的元素

BST的中序序列是升序序列。因此中序遍歷遍歷整個樹,同時計數,遍歷到第K個的時候返回值。

int count = 0;  // 記錄當前遍歷到第幾個元素
int result = 0; // 存儲第k小的元素值
// 中序遍歷(左→根→右)
void inorder(TreeNode* root, int k) {if (root == nullptr) return;        inorder(root->left, k);// 先遍歷左子樹// 處理當前節點:計數+1,若達到k則記錄結果count++;if (count == k) {result = root->val;return; // 找到后可提前返回,無需繼續遍歷}inorder(root->right, k);// 再遍歷右子樹
}
int kthSmallest(TreeNode* root, int k) {inorder(root, k);return result;
}

3.2眾數

  • 方法1(對于普通的二叉樹同樣適用):遍歷整個二叉樹,在遍歷過程中,用哈希表記錄每個元素的個數,然后找到元素出現最多的次數記錄下來,并將該元素返回給結果。
  • 方法2:搜索樹的中序遍歷是有序序列。利用這一個性質,
class Solution {
public:unordered_map<int,int> M;//遍歷并統計個數void f(TreeNode* root){if(root==nullptr) return;M[root->val]++;f(root->left);f(root->right);}vector<int> findMode(TreeNode* root) {vector<int> result;int count=1;if(root==nullptr) return result;f(root);//找到最大值for(auto m:M){if(m.second>count) count=m.second;}//填入resultfor(auto m:M){if(m.second==count) result.push_back(m.first);}return result;}
};

3.3兩數之和

給定一個二叉搜索樹 root 和一個目標結果 k,如果二叉搜索樹中存在兩個元素且它們的和等于給定的目標結果,則返回 true。

  • BST按照中序遍歷,將結果存儲在result中。
  • 利用雙指針快速定位目標。
vector<int> result;
void dfs(TreeNode* root){if(root==nullptr) return ;dfs(root->left);result.push_back(root->val);dfs(root->right);
}
bool findTarget(TreeNode* root, int k) {dfs(root);//利用雙指針,快速定位目標值int left=0;int right=result.size()-1;while(left<right){int sum=result[left]+result[right];if(sum==k) return 1;else if(sum<k) left++;else right--;}return 0;
}

3.4給定范圍的節點之和

給定二叉搜索樹的根結點 root,返回值位于范圍 [low, high] 之間的所有結點的值的和。

依然用BST的中序遍歷解決問題

int rangeSumBST(TreeNode* root, int low, int high) {if(root==nullptr) return 0;result.clear();dfs(root);int sum=0;for(int i=0;i<result.size();i++){if(result[i]>=low && result[i]<=high ) sum+=result[i];}return sum;
}

3.5節點最小距離

給你一個二叉搜索樹的根節點 root ,返回 樹中任意兩不同節點值之間的最小差值 。

轉換為中序有序序列之后計算。由于中序序列是有序的,因此離得越近,差值越小。

int minDiffInBST(TreeNode* root) {if(root==nullptr) return 0;result.clear();dfs(root);int m=INT_MAX;for(int i=0;i<result.size()-1;i++){m=min(m,result[i+1]-result[i]);}return m;}

3.6二叉搜索樹轉換為累加樹

在這里插入圖片描述

  • 二叉搜索樹的中序遍歷是一個單調遞增的有序序列。如果我們反序地中序遍歷該二叉搜索樹,即可得到一個單調遞減的有序序列。
  • 只需要反序中序遍歷該二叉搜索樹,記錄過程中的節點值之和,并不斷更新當前遍歷到的節點的節點值,即可得到題目要求的累加樹。
int sum=0;
TreeNode* convertBST(TreeNode* root) {if(root==nullptr) return root;convertBST(root->right);sum+=root->val;root->val=sum;convertBST(root->left);return root;
}

3.7最近結果查詢

給你一個 二叉搜索樹 的根節點 root ,和一個由正整數組成、長度為 n 的數組 queries 。
請你找出一個長度為 n 的 二維 答案數組 answer ,其中 answer[i] = [mini, maxi] :

  • mini 是樹中小于等于 queries[i] 的 最大值 。如果不存在這樣的值,則使用 -1 代替。
  • maxi 是樹中大于等于 queries[i] 的 最小值 。如果不存在這樣的值,則使用 -1 代替。
    返回數組 answer 。
    在這里插入圖片描述
  • lower_bound 是 C++ 標準庫 頭文件中的一個二分查找函數,用于在有序序列中查找第一個大于等于目標值的元素,返回該元素的迭代器
  • upper_bound:找第一個 > 目標值的元素(不包含等于的情況)。

中序遍歷序列為:[1,2,3,4,6,9,10]
查詢 q=5:
upper_bound找第一個 > 5 的元素是 6,前一個元素4→mini=4。
lower_bound找第一個≥5 的元素是 6→maxi=6。
結果為[4,6]。

// 中序遍歷BST,生成升序序列
void inorder(TreeNode* node, vector<int>& seq) {if (node == nullptr) return;inorder(node->left, seq);seq.push_back(node->val);inorder(node->right, seq);
}
vector<vector<int>> closestNodes(TreeNode* root, vector<int>& queries) {// 1.中序序列vector<int> inorderSeq;inorder(root, inorderSeq);vector<vector<int>> answer;for (int q : queries) {// 2. 對每個查詢,在有序序列中用二分查找找mini和maxiint mini = -1, maxi = -1;// 找mini:小于等于q的最大值(最后一個 <= q 的元素)auto it_mini = upper_bound(inorderSeq.begin(), inorderSeq.end(), q);if (it_mini != inorderSeq.begin()) {mini = *prev(it_mini);}// 找maxi:大于等于q的最小值(第一個 >= q 的元素)auto it_maxi = lower_bound(inorderSeq.begin(), inorderSeq.end(), q);if (it_maxi != inorderSeq.end()) {maxi = *it_maxi;}answer.push_back({mini, maxi});}return answer;
}

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

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

相關文章

ArkUI核心功能組件使用

1.Tabs&#xff08;選項卡&#xff09; 1.1 概述 Tabs組件的頁面組成包含兩個部分&#xff0c;分別是TabContent和TabBar。TabContent是內容頁&#xff0c;TabBar是導航頁簽欄。 TabBar是導航頁簽欄&#xff0c;頁面結構如下圖所示&#xff0c;根據不同的導航類型&#xff0c;布…

Qt5 多媒體大綱

一、入門準備 基礎知識 熟悉 Qt 的信號槽機制、事件循環 掌握 .pro 工程文件配置&#xff08;QT multimedia multimediawidgets&#xff09; 熟悉常見的音視頻格式與編解碼器基礎 環境配置 Qt Creator Qt 5.x 確認安裝了 multimedia 模塊與 mediaservice 插件 熟悉調試…

音頻數據集采樣率選擇建議

你好&#xff01;這是一個非常棒且非常重要的問題&#xff0c;在音頻機器學習項目中&#xff0c;選擇合適的采樣率是平衡計算效率和模型性能的關鍵。 直接回答你的問題&#xff1a;將音頻下采樣到 800 Hz 對于絕大多數音頻分類任務來說都太低了&#xff0c;幾乎肯定會丟失大量關…

深度學習系列 | Seq2Seq端到端翻譯模型

一、通俗總結Seq2Seq 就像一個 “序列轉換器”&#xff1a;先把輸入的一段話 “壓縮成一個核心意思”&#xff0c;再根據這個意思 “一句句生成另一段話”&#xff0c;能搞定翻譯、聽寫這類 “輸入輸出不一樣長” 的任務&#xff0c;但太長的內容可能記不全&#xff0c;還容易越…

Spring MVC BOOT 中體現的設計模式

Spring:創建型:單例模式:Bean默認就是單例的&#xff0c;是餓漢模式的&#xff0c;但是可以通過Lazy設置為懶漢工廠模式&#xff1a;可自定義FactroyBean&#xff0c;實現Bean自己的生產工廠結構型:代理模式&#xff1a;AOP就是典型的動態代理&#xff0c;有jdk和cglib兩種實現…

Chrome瀏覽器調用ActiveX控件之allWebOffice在線編輯控件

背景 allWebOffice控件能夠實現在瀏覽器窗口中在線操作文檔的應用&#xff08;閱讀、編輯、保存等&#xff09;&#xff0c;支持編輯文檔時保留修改痕跡&#xff0c;支持書簽位置內容動態填充&#xff0c;支持公文套紅&#xff0c;支持文檔保護控制等諸多辦公功能&#xff0c;本…

嵌入式 - 硬件:51單片機

本節重點1. MCU、CPU、GPU、NPU、SOC、MPU、FPU2. 內存、外存的區別3. RAM和ROM的區別&#xff0c;單片機RAM大小4. 三大總線及其特點5. 發光二極管分類及其特點6. 數碼管顯示原理一、嵌入式以應用為中心&#xff0c;以計算機技術為基礎&#xff0c;軟硬件可裁剪的專用計算機系…

Java Spring Boot 中 Redis 緩存穿透問題排查與解決方案

前言 作為一名普通的 Java 程序開發者&#xff0c;日常開發中難免會遇到一些看似簡單但實際排查起來非常棘手的問題。在最近的一個項目中&#xff0c;我遇到了一個 Redis 緩存穿透的問題&#xff0c;導致系統在高并發下性能急劇下降&#xff0c;甚至出現服務響應超時的情況。這…

Ubuntu下配置并遠程連接MySQL

1、安裝mysql-serverapt update apt install mysql-server2、修改配置文件/etc/mysql/mysql.conf.d/mysqld.cnfbind-address 0.0.0.0 mysqlx-bind-address 0.0.0.03、啟動并設置服務為開機自啟動systemctl enable mysql.service --now4、查看服務狀態systemct…

開源 C++ QT Widget 開發(九)圖表--儀表盤

文章的目的為了記錄使用C 進行QT Widget 開發學習的經歷。臨時學習&#xff0c;完成app的開發。開發流程和要點有些記憶模糊&#xff0c;趕緊記錄&#xff0c;防止忘記。 相關鏈接&#xff1a; 開源 C QT Widget 開發&#xff08;一&#xff09;工程文件結構-CSDN博客 開源…

怎么為服務器設置或重置服務器密碼?

創建服務器后&#xff0c;您可以設置服務器的登錄密碼&#xff0c;如果你忘記了密碼&#xff0c;可以重新設置實例的密碼。本文講一下如何重置阿里云服務器密碼。使用限制&#xff1a;離線重置密碼僅支持在控制臺設置或重置服務器管理員賬號的密碼。?Windows 實例的默認用戶名…

【線性代數入門 | 那忘算8】洛谷P3389 高斯消元(內附行列式教學)

想了想還是單開了一篇&#xff0c;數學王子值得&#xff01; 專欄指路&#xff1a;《再來一遍一定記住的算法&#xff08;那些你可能忘記了的算法&#xff09;》 前置知識&#xff1a; 矩陣&#xff1a;數的集合&#xff0c;一般是方程的系數。 題面&#xff1a; 洛谷P3389 …

GEM5學習(3):如何快速創建一個組件

通過一個圖并行計算的測試用例&#xff0c;來學習如何快速構建一個目標組件 其核心思想是通過繼承現有組件再拓展自定義參數 創建腳本 如何創建腳本&#xff0c;具體還可以看官方說明&#xff1a;gem5: Adding cache to configuration script mkdir configs/tutorial/part1/…

數據血緣中的圖數據庫如何選擇

Neo4j 和 ArangoDB 都是非常優秀的圖數據庫&#xff0c;但它們的設計哲學、核心架構和適用場景有顯著的區別。 簡單來說&#xff0c;核心區別在于&#xff1a; Neo4j 是原生圖數據庫&#xff0c;專為處理圖數據和圖查詢而設計和優化。ArangoDB 是多模型數據庫&#xff0c;同時支…

第27章學習筆記|學無止境:從“會用命令”到“會做工具”的進階路線

第27章學習筆記|學無止境:從“會用命令”到“會做工具”的進階路線 你已經能用 PowerShell 解決很多日常問題了。接下來最重要的,就是把零散命令升級為可復用的工具,并在真實場景中不斷打磨。 一、為什么下一步是“工具化(Toolmaking)” 當任務開始“重復、多人用、可移…

C++編程語言:標準庫:第37章——正則表達式(Bjarne Stroustrup)

第 37章 正則表達式(Regular Expressions) 目錄 37.1 正則表達式(規范表達式)(Regular Expressions) 37.1.1 正則表達式相關符號(Regular Express Notation) 37.2 regex 37.2.1 匹配結果(Match Results) 37.2.2 格式化(Formatting) 37.3 正則表達式函數 37.3.1 …

sciml包scixgboost函數發布,輕松完成機器學習xgboost分析

Xgboost是Boosting算法的其中一種&#xff0c;Boosting算法的思想是將許多弱分類器集成在一起&#xff0c;形成一個強分類器。因為Xgboost是一種提升樹模型&#xff0c;所以它是將許多樹模型集成在一起&#xff0c;形成一個很強的分類器。 我目前整合了多個R包&#xff0c;編寫…

Ubuntu中配置JMmeter工具

1、檢查是否已安裝Java 環境java -version若未安裝&#xff0c;執行以下命令安裝 OpenJDKsudo apt update sudo apt install openjdk-11-jdk # 或 openjdk-17-jdk2、用wget直接下載JMeter壓縮包wget https://dlcdn.apache.org/jmeter/binaries/apache-jmeter-5.6.3.tgz將下載的…

LeetCode 925.長按鍵入

你的朋友正在使用鍵盤輸入他的名字 name。偶爾&#xff0c;在鍵入字符 c 時&#xff0c;按鍵可能會被長按&#xff0c;而字符可能被輸入 1 次或多次。 你將會檢查鍵盤輸入的字符 typed。如果它對應的可能是你的朋友的名字&#xff08;其中一些字符可能被長按&#xff09;&#…

9.3 模擬

lc190 顛倒二進制ret (ret << 1) (n >> i & 1);class Solution { public:uint32_t reverseBits(uint32_t n) {uint32_t ret 0;for (int i 0; i < 32; i)ret (ret << 1) (n >> i & 1);return ret;} };lc14 flag checkclass Solution {…